
package com.ys.chatserver.http.logic;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.eva.epc.common.util.CommonUtils;
import com.eva.epc.common.util.EException;
import com.eva.framework.Processor;
import com.eva.framework.dbpool.DBDepend;
import com.eva.framework.dbpool.DBShell;
import com.eva.framework.dto.SysActionConst;
import com.eva.framework.utils.EndsExceptionFactory;
import com.eva.framework.utils.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ys.chatserver.BaseConf;
import com.ys.chatserver.cache.GroupsInfoCacheProvider;
import com.ys.chatserver.cache.GroupsMembersCacheProvider;
import com.ys.chatserver.cache.dto.GroupMember4Cache;
import com.ys.chatserver.common.dto.cnst.RtcRedisKeyConstants;
import com.ys.chatserver.common.dto.cnst.UserProtocalsType;
import com.ys.chatserver.http.logic.dto.*;
import com.ys.chatserver.im.ChatServerEventListener;
import com.ys.chatserver.im.dto.ChannelEntity;
import com.ys.chatserver.im.dto.CircleChannel;
import com.ys.chatserver.im.dto.NodeType;
import com.ys.chatserver.im.impl.ChatLogicManager4Group;
import com.ys.chatserver.im.impl.UsersStatusManager;
import com.ys.chatserver.im.util.MessageHelper;
import com.ys.chatserver.redis.RedisUtil;
import com.ys.chatserver.tool.EmptyUtils;
import com.ys.chatserver.tool.IdUtils;
import org.slf4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_PATTERN;

/**
 * 群组相关的Http接口处理器实现类。
 *
 * @author Json
 * @since 4.3
 */
public class GroupChatProcessor implements SysActionConst, Processor {

    Logger logger = LoggerFactory.getLog();

    /**
     * 群组名称最大29个字符（中文算1个字符）
     */
    public final static int GROUP_NAME_MAX_LENGTH = 29;

    public static DBShell db = new DBShell();

    /**
     * 处理器的核心实现方法.<br>
     * 可据job_dispatch_id找到对应的JobDispatcher，JobDispatcher又能据
     * action_id进行对应动作的处理，以完成本次操作请求.
     *
     * @param job_dispatch_id 作业调度ID
     * @param action_id       动作ID
     * @param _newData        客端发送过来的本次修改新数据(可能为空，理论上与oldData不会同时空）
     * @param _oldData        客端发送过来的本次修改前的老数据(可能为空，理论上与newData不会同时空）
     * @param user            user 包含该请求用户完整个人信息封装对象（该对象来自于成功登陆后存放于session中的值）
     * @return 任意类型返回值
     * @throws Exception
     */
    @Override
    public Object process(int job_dispatch_id, int action_id, Object _newData, Object _oldData, User user)
            throws Exception {
        Object ret = null;
        String newDataJSON = (String) _newData;

        switch (job_dispatch_id) {
            // 处理服务端对外提供的群基本信息管理等
            case JobDispatchConst.LOGIC_GROUP_BASE_MGR:
                ret = maintainMgrGroupBaseJobDispatcher(action_id, newDataJSON, _oldData, user);
                break;
            // 处理服务端对外提供的群组相关信息查询等
            case JobDispatchConst.LOGIC_GROUP_QUERY_MGR:
                ret = maintainMgrGroupQueryJobDispatcher(action_id, newDataJSON, _oldData, user);
                break;
            default:
                throw EndsExceptionFactory.INVALID_JOB_DISPATCHER_ID(job_dispatch_id);
        }
        return ret;
    }

    /**
     * 维护群组基本信息管理.
     *
     * @param action_id   维护类型，SysConstant中的操作类型常量
     * @param newDataJSON 客端发送过来的本次修改新数据(可能为空，理论上与oldData不会同时空）
     * @param oldData     客端发送过来的本次修改前的老数据(可能为空，理论上与newData不会同时空）
     * @param user        操作者的用户名
     * @return 返回给客户端的对象
     */
    public String maintainMgrGroupBaseJobDispatcher(int action_id, String newDataJSON
            , Object oldData, User user) throws Exception {
        Vector<Object> sqls = new Vector<>(2);
        Vector<Object> values = new Vector<>(2);

        switch (action_id) {
            // 【接口1016-24-68】修改节点
            case ACTION_UPDATE_CHANNEL_NAME:
                JSONObject ob = JSONObject.parseObject(newDataJSON);
                final String baseId = ob.getString("g_id");
                final String channelId = ob.getString("id");
                final String noname = ob.getString("name");
                db.update(Collections.singletonList("update chat_group_node set node_name = '" + noname + "' where node_id = '" + channelId + "' and base_id = '" + baseId + "'"), true);

                new Thread(() -> {
                    // ** 【高速缓存】：即时更新群缓存数据（因为新建了此群）
                    GroupsInfoCacheProvider.getInstance().reloadOneFromDB(baseId + "_" + channelId);

                    // 【实时通知】：向群员发送一条通知（除修改者之外）
                    ChatLogicManager4Group.batchNotification4GroupNameChangedAsync("修改群名"
                            , user.getUserId(), user.getNickname(), noname
                            , GroupsMembersCacheProvider.getInstance().get(baseId + "_" + channelId).values()
                            , baseId);
                }).start();
                return "1";
            // 【接口1016-24-63】删除树节点
            case ACTION_CHANNEL_DELETE: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                final String gId = nwObj.getString("g_id");
                final String id = nwObj.getString("id");
                final String type = nwObj.getString("type");
                final String pid = nwObj.getString("p_id");
                try {
                    // 有人不能删除
                    if (Objects.equals(type, "1")) {
//                        List<String> userNodeIds = new ArrayList<>();
//                        iterateUserId(id, userNodeIds);
//                        if (!userNodeIds.isEmpty()) {
//                            return "0";
//                        }
                        List<String> childIds = Stream.of(id).collect(Collectors.toList());
                        iterateNodeId(id, childIds);
                        if (!childIds.isEmpty()) {
                            try {
                                db.update(Collections.singletonList("update chat_group_node set g_status = -1 where  base_id = '" + gId + "' and node_id in ('" + String.join("','", childIds) + "')"), true);
                            } catch (Exception e) {
                                logger.error("递归删除子节点频道或者用户失败", e);
                                throw new RuntimeException(e);
                            }
                            sendRefresh(gId, UserProtocalsType.MT53_OF_GROUP$SYSCMD_CHANNEL$CREATE_CHANNEL$SERVER);
                        }
                    }
                    if (Objects.equals(type, "2")) {
                        Vector<Vector<?>> rootManager = db.queryData("select m_ids from chat_group_node where g_status = 1 and node_pid is null and base_id = '" + gId + "'");
                        if (rootManager.get(0).get(0).toString().contains(id)) {
                            throw new EException("该用户是根节点管理员不能删除");
                        } else {
                            db.update(Collections.singletonList("update chat_group_node set g_status = -1 where node_type = 'USER' and node_pid = '" + pid + "' and  base_id = '" + gId + "' and user_uid = '" + id + "'"), true);
                            // 更新群成员人数
                            prepareUpdateChannelMemberCount(sqls, values, pid);
                            GroupsMembersCacheProvider.getInstance().reloadOneFromDB(gId + "_" + pid);
                            //通知此次被删除的人、通知群里的其他余下的人
                            new Thread(() -> {
                                try {
                                    // 通知刷新频道列表
                                    MessageHelper.sendMessage(user.getUserId(), "", false, null, UserProtocalsType.REFRESH_CHANNEL_LIST, null);

                                    // 通知群成员
                                    Vector<Vector<?>> vectors = db.queryData("select nickname from g_users where del_flag = 0 and user_uid = '" + id + "'");
                                    ArrayList<GroupMemberEntity> membersBeDeleteList = new ArrayList<>();
                                    GroupMemberEntity gme = new GroupMemberEntity();
                                    gme.setUser_uid(id);
                                    gme.setNickname(vectors.get(0).get(0).toString());
                                    membersBeDeleteList.add(gme);
                                    ChatLogicManager4Group.batchNotification4SomeoneBeRemovedAsync(
                                            "删除群员", user.getUserId(), user.getNickname()
                                            , membersBeDeleteList
                                            , GroupsMembersCacheProvider.getInstance().get(gId + "_" + pid).values()
                                            , gId + "_" + pid
                                    );
                                } catch (Exception e) {
                                    logger.error("通知下线失败:" + e.getMessage(), e);
                                }
                            }).start();
                        }
                    }
                    return "1";
                } catch (Exception e) {
                    logger.error("删除频道或者用户节点失败", e);
                }
                return "0";
            }
            // 【接口1016-24-7】添加群或者树节点
            case ACTION_APPEND1: {
                String time = DateUtil.format(new Date(), NORM_DATETIME_PATTERN);
                LoggerFactory.getLog().debug("==【【【【【【【正在创建群。。。】】】】】】】==");
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                // 群主（实际就是本次群的创建者）
                final String ownerUid = nwObj.getString("owner_uid") == null ? user.getUserId() : nwObj.getString("owner_uid");
                // 群主昵称（实际就是本次群的创建者）
                final String ownerNickName = nwObj.getString("owner_nickname");
                // 父节点id
                final String pid = nwObj.getString("p_id");
                // 群组名称或者频道名称
                final String name = nwObj.getString("name");
                // 节点类型(0-群,1-频道,2-用户)
                final String type = nwObj.getString("type");
                // 是否可见其他频道
                final String visible = nwObj.getString("visible") == null ? "0" : nwObj.getString("visible");
                // 群组id
                final String gId = nwObj.getString("g_id");

                //用户id
                final String members = nwObj.getString("members");

                String srcFrom = EmptyUtils.isNotEmpty(nwObj.getString("src_from")) ? nwObj.getString("src_from") : "0";              // 加群来源，"0"表示通过邀请加群、"1"表示通过扫描二难码加群，默认可为null（为null将默认是通过邀请加群）

                // 主键
                String newGid = IdUtils.getNumberUuid();
                // 时间
                // 插入群
                if (Objects.equals(type, "0")) {
                    Vector<Vector<?>> vectors = db.queryData("select nickname from g_users where del_flag = 0 and user_uid = '" + user.getUserId() + "'");
                    sqls.add("INSERT INTO chat_group_base(g_id,g_status,g_name,g_owner_user_uid,create_user_uid,create_time)" +
                            " VALUES(?,?,?,?,?,?)");
                    values.add(new Object[]{newGid, "1", name, ownerUid, ownerUid, time});

                    sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_type,node_rid,node_name,create_time,create_user_uid,m_ids,level" +
                            ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)");
                    values.add(new Object[]{newGid, "0", newGid, time, ownerUid, time, NodeType.MAIN_CHANNEL.name(), newGid, name, time, user.getUserId(), "," + user.getUserId() + ",", 1});

                    String dateTime = DateUtil.format(new Date(System.currentTimeMillis() + 1000), NORM_DATETIME_PATTERN);
                    sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_type,node_rid,node_name,create_time,create_user_uid,m_ids,node_pid,level" +
                            ") VALUES(?,?,?,?,?,?,?,?,?,? ,?,?,?,?)");
                    values.add(new Object[]{IdUtils.getNumberUuid(), user.getUserId(), newGid, dateTime, ownerUid, dateTime, NodeType.USER.name(), newGid, vectors.get(0).get(0).toString(), dateTime, user.getUserId(), "," + user.getUserId() + ",", newGid, 2});
                    LogicProcessor2.db.update(sqls, values, true);
                }
                // 插入频道
                if (Objects.equals(type, "1") && Objects.nonNull(pid)) {
                    Vector<Vector<?>> parentChannel = db.queryData("select m_ids,level,s_ids from chat_group_node where node_id = '" + pid + "'");
                    if (!parentChannel.isEmpty()) {
                        String mIds = parentChannel.get(0).get(0).toString();
                        int level = Integer.parseInt(parentChannel.get(0).get(1).toString());
                        String sIds = parentChannel.get(0).get(2).toString();
                        // if (mIds.contains("," + user.getUserId() + ",")) {
                        sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid,visible,node_name,create_time,create_user_uid,m_ids,level,s_ids" +
                                ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
                        values.add(new Object[]{newGid, "0", gId, time, ownerUid, time, pid, NodeType.MAIN_CHANNEL.name(), gId, visible, name, time, user.getUserId(), mIds, level + 1, sIds});
                        LogicProcessor2.db.update(sqls, values, true);
                        //    }
                        sendRefresh(gId, UserProtocalsType.MT53_OF_GROUP$SYSCMD_CHANNEL$CREATE_CHANNEL$SERVER);
                    }
                }
                // 插入用户
                if (Objects.equals(type, "2") && JSON.isValidArray(members)) {
                    Vector<Vector<?>> parentChannel = db.queryData("select m_ids,level,s_ids from chat_group_node where node_id = '" + pid + "'");
                    if (!parentChannel.isEmpty()) {
                        String mIds = parentChannel.get(0).get(0).toString();
                        int level = Integer.parseInt(parentChannel.get(0).get(1).toString());
                        String sIds = parentChannel.get(0).get(2).toString();
//                        if (mIds.contains("," + user.getUserId() + ",")) {
                            JSONArray objects = JSON.parseArray(members);
                            for (Object object : objects) {
                                String nodeId = IdUtils.get8Uuid();
                                JSONObject next = (JSONObject) object;
                                String userUid = next.getString("user_uid");
                                Vector<Vector<?>> count = db.queryData("select count(1) from chat_group_node where node_pid = '" + pid + "' and base_id = '" + gId + "' and g_status = 1 and node_type = 'USER' and user_uid = '" + userUid + "'");
                                if (count.get(0).get(0).equals("0")) {
                                    String nickname = next.getString("nickname");
                                    sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid,visible,node_name,create_time,create_user_uid,m_ids,level,s_ids" +
                                            ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
                                    values.add(new Object[]{nodeId, userUid, gId, time, ownerUid, time, pid, NodeType.USER.name(), gId, visible, nickname, time, user.getUserId(), mIds, level + 1, sIds});
                                }
                            }
                            prepareUpdateChannelMemberCount(sqls, values, pid);
                            LogicProcessor2.db.update(sqls, values, true);
                            GroupsMembersCacheProvider.getInstance().reloadOneFromDB(gId + "_" + pid);
//                        }
                    }
                }

                try {
                    if (EmptyUtils.isNotEmpty(pid) && Objects.equals(type, "1")) {
                        db.update(Collections.singletonList("update chat_group_node set have_child = true where node_id = '" + pid + "'"), true);
                    }
                } catch (Exception e) {
                    logger.error("update have_child exception", e);
                }
                // 将本次创建成功的群基本信息查询出来（将返回给客户端使用）
                String id = Objects.equals(type, "2") ? pid : newGid;

                GroupEntity newGroupInfoReturn = this.queryChannelInfo(id, user.getUserId());// 第2个参数null表示不需要取”我“在本群中的昵称，因为刚建的群还来不及设置群昵称呢
                if (Objects.equals(type, "2") && JSON.isValidArray(members)) {
                    new Thread(() -> {
                        try {
                            ArrayList<GroupMemberEntity> newJoinedMemberList = new ArrayList<>();
                            ConcurrentHashMap<String, GroupMember4Cache> hashMap = GroupsMembersCacheProvider.getInstance().get(gId + "_" + pid);
                            Collection<GroupMember4Cache> oldMemberList = hashMap == null ? null : hashMap.values();
                            JSONArray objects = JSON.parseArray(members);
                            for (Object object : objects) {
                                JSONObject next = (JSONObject) object;
                                String userUid = next.getString("user_uid");
                                String nickname = next.getString("nickname");
                                GroupMemberEntity groupMemberEntity = new GroupMemberEntity();
                                groupMemberEntity.setUser_uid(userUid);
                                groupMemberEntity.setNickname(nickname);
                                groupMemberEntity.setG_id(gId);
                                newJoinedMemberList.add(groupMemberEntity);
                            }
                            inviteNotify(gId, user.getUserId(), user.getNickname(), srcFrom, newJoinedMemberList, oldMemberList, newGroupInfoReturn, pid);
                        } catch (Exception e) {
                            logger.error("通知邀请人失败:" + e.getMessage(), e);
                        }
                    }).start();
                }

                //** 返回值(返回值“0”表示本次建群失败！)
                return newGroupInfoReturn == null ? "0" : JSON.toJSONString(newGroupInfoReturn);
            }
            // 【接口1016-24-8】修改群名称
            case ACTION_APPEND2: {
                LoggerFactory.getLog().debug("==【【【【【【【正在修改群名。。。】】】】】】】==");
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                String modify_by_uid = nwObj.getString("modify_by_uid");
                String modify_by_nickname = nwObj.getString("modify_by_nickname");
                String newGroupName = nwObj.getString("group_name");
                String gid = nwObj.getString("gid");

                sqls.add("UPDATE chat_group_base SET g_name=? WHERE g_id=?");
                values.add(new Object[]{newGroupName, gid});
                boolean res = db.update(sqls, values, true);

                // ** 【高速缓存】：即时更新群缓存数据（因为新建了此群）
                GroupsInfoCacheProvider.getInstance().reloadOneFromDB(gid);

                // 【实时通知】：向群员发送一条通知（除修改者之外）
//                ChatLogicManager4Group.batchNotification4GroupNameChangedAsync("修改群名"
//                        , modify_by_uid, modify_by_nickname, newGroupName
////						, this.queryGroupMemberList(gid)
//                        // 从高速缓存中读取群成员列表，提升性能
//                        , GroupsMembersCacheProvider.getInstance().get(gid).values()
//                        , gid);

                return res ? "1" : "0";// 1 表示更新成功，否则失败
            }
            // 【接口1016-24-9】修改"我"的群昵称
            case ACTION_APPEND3: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);

                sqls.add("UPDATE chat_group_node SET nickname_ingroup = ? WHERE base_id = ? and user_uid = ? ");
                values.add(new Object[]{nwObj.getString("nickname_ingroup"), nwObj.getString("gid"), nwObj.getString("user_uid")});
                boolean res = db.update(sqls, values, true);

                return res ? "1" : "0";// 1 表示更新成功，否则失败
            }
            // 【接口1016-24-22】修改群公告（仅开放给群主）
            case ACTION_APPEND4: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);

                String g_notice_updateuid = nwObj.getString("g_notice_updateuid");
                String g_id = nwObj.getString("g_id");

                String ret = "-1";    // 返回值：未定义

                if (!queryChannelOwner(g_id, g_notice_updateuid)) {
                    ret = "2";        // 返回值：修改人已不是群主，本次修改失败！
                } else {
                    sqls.add("UPDATE chat_group_node SET g_notice= ?,g_notice_updatetime = " + DBDepend.getDefaultDatetimeFunc()
                            + ",g_notice_updateuid=? WHERE base_id=? and g_owner_user_uid=?");
                    values.add(new Object[]{nwObj.getString("g_notice"), g_notice_updateuid, g_id, g_notice_updateuid});
                    boolean res = db.update(sqls, values, true);

                    if (res)
                        ret = "1";    // 返回值：本次修改成功
                }
                return ret;
            }
            // 【接口1016-24-23】删除群成员或退群 接口
            case ACTION_APPEND5: {
                boolean sucess = false;
                try {
                    LoggerFactory.getLog().debug("==【【【【【【【正在删除群成员或退群。。。】】】】】】】==");

                    JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                    // 本次删除的操作人uid（群主踢人时本参数为群主，如果是用户自已退出退路时本参数为退出者自已）
                    final String del_opr_uid = nwObj.getString("del_opr_uid");
                    // 本次删除的操作人昵称
                    final String del_opr_nickname = nwObj.getString("del_opr_nickname");
                    // 本次删除发生的群id
                    final String gid = nwObj.getString("gid");
//					// 本次删除发生的群名称
//					final String gname = nwObj.getString("gname");
                    // 要删除的群成员
                    String membersJSON = nwObj.getString("members");

                    GroupEntity newGroupInfoReturn = null;

                    final ArrayList<ArrayList<?>> membersBeDelete = new Gson().fromJson(membersJSON
                            , new TypeToken<ArrayList<ArrayList<?>>>() {
                            }.getType());

//					ArrayList<ArrayList> membersBeDelete = new Gson().fromJson(newDataJSON
//							, new TypeToken<ArrayList<ArrayList>>(){}.getType()); 

                    // 要被删除的群员（用GroupMemberEntity组织的集合，调用其它方法时好用一些）
                    ArrayList<GroupMemberEntity> membersBeDeleteList = new ArrayList<GroupMemberEntity>();
//					
                    if (membersBeDelete != null && !membersBeDelete.isEmpty()) {
                        for (ArrayList<?> row : membersBeDelete) {
                            // 以下字段及顺序请确保与客户端的接口请求保持一致！
//							String gid = (String)row.get(0);
                            String userId = (String) row.get(1);
                            String nickName = (String) row.get(2);

                            // 将群员的基本信息存到一个集合中备用
                            GroupMemberEntity gme = new GroupMemberEntity();
                            gme.setUser_uid(userId);
                            gme.setNickname(nickName);
                            membersBeDeleteList.add(gme);

                            sqls.add("delete from chat_group_node where base_id = ? and user_uid = ? " +
                                    //## Bug FIX 20190330 START:
                                    //## 强制检查被删除者是否是群主，如果是群主，应该由它使用“解散群”而不是“退群”功能，否则上
                                    //## 会出现群主已经从群里退出的数据不一致情况（这种情况多发生于群主已转给“我”，但界面数据没
                                    //## 来的及刷新的情况下，以为还是普通群员，而点了“退群”按钮时）
                                    "	and user_uid <> (SELECT g_owner_user_uid FROM chat_group_base WHERE g_id=?) ");
                            //## Bug FIX 20190330 END:

                            values.add(new Object[]{gid, userId, gid});
                        }
                    }

                    // 更新群成员人数
                    prepareUpdateGroupMemberCount(sqls, values, gid);

                    db.update(sqls, values, false);
                    sucess = true;

                    // ** 【生成群头像】：暂时未使用异步方式，原因是希望阻止用户频繁
                    //                   删除群员并生成头像，因为这样会导致更多的服务端性消耗
                    // 说明：放在通知前面生成头像，是希望在群员收到通知时，最新群头像早已生成完毕。
                    GroupAvatarHelper.generateGroupAvatar(gid);

                    // ** 【高速缓存】：将最新群成员数据更新到高速缓存中（以便后绪使用）
                    // TODO: 未来优化空间：直接要删除的集合来更新缓存，可节省一次db查询，暂时可先不折腾
                    GroupsMembersCacheProvider.getInstance().reloadOneFromDB(gid);

                    // 【实时通知】：通知此次被删除的人、通知群里的其他余下的人
                    ChatLogicManager4Group.batchNotification4SomeoneBeRemovedAsync(
                            "删除群员", del_opr_uid, del_opr_nickname
                            , membersBeDeleteList
//							, this.queryGroupMemberList(gid)
                            // 从高速缓存中读取群成员列表，提升性能
                            , GroupsMembersCacheProvider.getInstance().get(gid).values()
                            , gid
//							, gname
                    );
                } catch (Exception e) {
                    LoggerFactory.getLog().debug(e.getMessage(), e);
                }


                return sucess ? "1" : "0";// 1 表示更新成功，否则失败
            }
            // 【接口1016-24-24】邀请入群/扫码入群接口
            case ACTION_APPEND6: {
                LoggerFactory.getLog().debug("==【【【【【【【正在邀请入群群。。。】】】】】】】==");

                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                String srcFrom = nwObj.getString("src_from");              // 加群来源，"0"表示通过邀请加群、"1"表示通过扫描二难码加群，默认可为null（为null将默认是通过邀请加群）
                if (CommonUtils.isStringEmpty(srcFrom, true))
                    srcFrom = "0";
                String inviteUid = nwObj.getString("invite_uid");          // 邀请发起人或二维码分享者的uid
                String inviteNickName = nwObj.getString("invite_nickname");// 邀请发起人或二维码分享者的昵称
                String inviteToGid = nwObj.getString("invite_to_gid");     // 邀请至群id
                String membersBeInviteJSON = nwObj.getString("members");   // 被邀请的成员

                // 新加群员列表
                ArrayList<GroupMemberEntity> newJoinedMemberList = new ArrayList<>();
                // 老群员列表
                Collection<GroupMember4Cache> oldMemberList = new ArrayList<>();

                ArrayList<ArrayList<?>> membersBeInvite = new Gson().fromJson(membersBeInviteJSON, new TypeToken<ArrayList<?>>() {
                }.getType());
                if (!CommonUtils.isStringEmpty(inviteUid) && membersBeInvite != null && !membersBeInvite.isEmpty()) {
                    // 查询老群员列表备用
//					oldMemberList = queryGroupMemberList(inviteToGid);
                    // 从高速缓存中读取群成员列表，提升性能
                    oldMemberList = GroupsMembersCacheProvider.getInstance().get(inviteToGid).values();

                    // 持久化新群员
                    for (ArrayList<?> row : membersBeInvite) {
                        // 以下字段及顺序请确保与客户端的接口请求保持一致！
                        String gid = (String) row.get(0);
                        String userId = (String) row.get(1);
                        String nickname = (String) row.get(2);

                        // 将群员的基本信息存到一个集合中备用
                        GroupMemberEntity newGme = new GroupMemberEntity();
                        newGme.setUser_uid(userId);
                        newGme.setNickname(nickname);
                        newJoinedMemberList.add(newGme);

                        // 如果本次要邀请的人确实不在db中，则加入之（否则无需重复加入）
                        if (db.queryData("select 1 from chat_group_node where base_id='" + gid + "' and user_uid='" + userId + "'").size() <= 0) {
                            Vector<Vector<?>> mainNode = db.queryData("select node_rid from chat_group_node where base_id='" + gid + "' and node_type='" + NodeType.USER.name() + "'");
                            if (!mainNode.isEmpty()) {
                                prepareInsertMemberToGroup(sqls, values, userId, gid, inviteUid, (String) mainNode.get(0).get(0), NodeType.USER.name(), (String) mainNode.get(0).get(0));
                            }
                        }
                    }
                }

                // 更新群成员总人数
                prepareUpdateGroupMemberCount(sqls, values, inviteToGid);

                boolean res = db.update(sqls, values, false);

                // ** 【生成群头像】：暂时未使用异步方式，原因是希望阻止用户频繁
                //                   邀请群员并生成头像，因为这样会导致更多的服务端性消耗
                // 说明：放在通知前面生成头像，是希望在群员收到通知时，最新群头像早已生成完毕。
                GroupAvatarHelper.generateGroupAvatar(inviteToGid);

                // 【实时通知】：通知新加入的人（“他”加群成功）和老群员（有人加群了）
                ChatLogicManager4Group.batchNotification4InviteMembersAsync(
                        srcFrom
                        , "群聊CMD-邀请通知"
                        , inviteUid, inviteNickName
                        , newJoinedMemberList
                        , oldMemberList
                        , this.queryGroupInfo(inviteToGid, null));

                // ** 【高速缓存】：将最新群成员数据更新到高速缓存中（以便后绪使用）
                // TODO: 未来优化空间：直接用新进成员集合，可节省一次db查询，暂时可先不折腾
                GroupsMembersCacheProvider.getInstance().reloadOneFromDB(inviteToGid);

                return res ? "1" : "0";// 1 表示更新成功，否则失败
            }

            // 【接口1016-24-25】转让本群（仅开放给群主）接口
            case ACTION_APPEND7: {
                LoggerFactory.getLog().debug("==【【【【【【【正在转让群。。。】】】】】】】==");

                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                String oldOwnerUid = nwObj.getString("old_owner_uid");           // 原群主uid
//				String oldOwnerNickname = nwObj.getString("old_owner_nickname"); // 原群主昵称
                String newOwnerUid = nwObj.getString("new_owner_uid");           // 新群主uid（即将被转让为群主）
                String newOwnerNickname = nwObj.getString("new_owner_nickname"); // 新群主昵称
                String gid = nwObj.getString("g_id");                   // 转让发生的群
//				String gname = nwObj.getString("g_name");                   // 转让发生的群名

                String ret = "-1";    // 返回值：未定义

                if (!queryGroupOwner(gid, oldOwnerUid)) {
                    ret = "2";        // 返回值：转让发起人已不是群主，本次转让失败！
                } else {
                    if (db.queryData("select 1 from chat_group_node where user_uid='"
                            + newOwnerUid + "' and base_id = '" + gid + "'").size() <= 0) {
                        ret = "3";    // 返回值：被转让人不是群成员，本次转让失败！
                    } else {
                        // 设置新群主
                        sqls.add("update chat_group_base set g_owner_user_uid=? where g_id=? and g_owner_user_uid=?");
                        values.add(new Object[]{newOwnerUid, gid, oldOwnerUid});

                        // 更新新群主成为群主的时间
                        sqls.add("update chat_group_node set be_owner_time=" + DBDepend.getDefaultDatetimeFunc()
                                + " where base_id =? and user_uid=?");
                        values.add(new Object[]{gid, newOwnerUid});

                        boolean res = db.update(sqls, values, false);
                        if (res)
                            ret = "1"; // 返回值：本次转让成功

                        // 【实时通知】：向群员发送一条通知（除修改者之外）
                        ChatLogicManager4Group.batchNotification4CommonInfoAsync("转让群主"
                                , "\"" + newOwnerNickname + "\"已成为新群主"
//								, this.queryGroupMemberList(gid)
                                // 从高速缓存中读取群成员列表，提升性能
                                , GroupsMembersCacheProvider.getInstance().get(gid).values()
                                , gid
//								, gname
                                // 原群主（也就是本次转让发起人）就不需要通知它自已了
                                , oldOwnerUid
                        );
                    }
                }

                return ret;
            }
            // 【接口1016-24-26】解散群（仅开放给群主）接口
            case ACTION_APPEND8: {
                LoggerFactory.getLog().debug("==【【【【【【【正在解散群。。。】】】】】】】==");

                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                String ownerUid = nwObj.getString("owner_uid");           // 群主uid(也就是解散的发起人)
                String ownerNickname = nwObj.getString("owner_nickname"); // 群主昵称
                String gid = nwObj.getString("g_id");                     // 将要被解散的群
//				String gname = nwObj.getString("g_name");                 // 将要被解散的群名

                String ret = "-1"; // 返回值：未定义

                if (!queryGroupOwner(gid, ownerUid)) {
                    ret = "2";     // 返回值：解散发起人已不是群主，本次解散失败！
                } else {
                    try {
                        // 群解散前先取出所有群员列表（以备通知）
                        //					ArrayList<GroupMember4Cache> allMembersBeforeDismiss = this.queryGroupMemberList(gid);
                        // 从高速缓存中读取群成员列表，提升性能
                        Collection<GroupMember4Cache> allMembersBeforeDismiss =
                                GroupsMembersCacheProvider.getInstance().get(gid).values();

                        //** 先存档该群所有未超期的聊天记录（已超期的会自动存档哦）
                        if (!db.queryData("select 1 from chat_msgs_collect where chat_type=2 and dest_uid=" + gid).isEmpty()) {
                            LoggerFactory.getLog().debug("[群解解散时]该群存在未被存档的聊天记录，解散群时也将一并转储之...");

                            // 先将聊天记录插入到存档表中
                            sqls.add(TimmingRestoreMessages.COPY_CHATTING_MESSAGES_TO_ACHIVED_SQL + " where chat_type=2 and dest_uid=?");
                            values.add(new Object[]{gid});

                            // 再将聊天记录从聊天记录表中移除
                            sqls.add(TimmingRestoreMessages.DELETE_CHATTING_MESSAGES_SQL + " where chat_type=2 and dest_uid=?");
                            values.add(new Object[]{gid});
                        }

                        //** 先删除所有未被收取的本群离线消息（微信也是这样的）
                        if (!db.queryData("select 1 from chat_offline_history where group_id = '" + gid + "'").isEmpty()) {
                            LoggerFactory.getLog().debug("[群解解散时]该群存在未被拉取的离线消息，解散群时也将一并删除之...");

                            sqls.add("delete from chat_offline_history where group_id=?");
                            values.add(new Object[]{gid});
                        }

                        //** 再删除所有成员
                        sqls.add("delete from chat_group_node where base_id =?");
                        values.add(new Object[]{gid});

                        //** 再更新群基本信息中的状态字段
                        // 补充说明：群解散时，将删除群成员、群友没有收取的离线聊天记录（微信也是这样），
                        //          但不会删除群基本信息（只设状态为-1)，因为解散群的离线通知、公司
                        //          的后台运营时，可能需要群的基本信息，用于提供基顾数据，所以不应把群
                        //          基本信息也删除了。
                        //					sqls.add("delete from chat_group_base where g_id=?");
                        sqls.add("update chat_group_base set g_status=-1,del_user_uid=?,del_time=" + DBDepend.getDefaultDatetimeFunc()
                                + " where g_rid=?");
                        values.add(new Object[]{ownerUid, gid});

                        // 更新群成员人数
                        prepareUpdateGroupMemberCount(sqls, values, gid);

                        boolean res = db.update(sqls, values, true);
                        if (res)
                            ret = "1"; // 返回值：本次解散成功

                        // 【实时通知】：通知除群主外的所有人
                        ChatLogicManager4Group.batchNotification4GroupDismissedAsync("群被解散"
                                , allMembersBeforeDismiss, gid
                                //							, gname
                                , ownerUid, ownerNickname);

                        // ** 【高速缓存】：从高速缓存中删除此群成员数据
                        //					GroupsMembersCacheProvider.getInstance().reloadGroupFromDB(gid);
                        GroupsMembersCacheProvider.getInstance().remove(gid);

                        // ** 【高速缓存】：从高速缓存中删除此群（因为解散了此群）
                        //					GroupsInfoCacheProvider.getInstance().reloadOneFromDB(gid);
                        //# TODO: 为解决群解散时，离线APNS推送逻辑不能走完的bug而暂时注释了以下代码。
						/* 为了让上方离线消息的APNS推送代码更内聚，推送时需要的群名称等基本信息，
						是实时查高速缓存实现的，这样做的目的是提升离线消息处理代码的调用简单性。
						但带来的问题是，当以下代码执行时（即从高速缓存中去掉已解散的群基本信息），
						离线APNS推送逻辑就没法正常走完了（因为需要的群基本信息已不能从高速缓存中
						查到）。那么长此以往，被解散群的基本信息就留在内存里（直到下次重启）。
						解决办法可以是：为此缓存加一个解散时间，可以设定多长时间后，由单独的定时器
						来清楚，这样更合理。但实际上不清理，也占用不了多少内存，。单独维护清理逻辑
						反而得不偿失，可以先按现在的逻辑实现吧，以后进行高效架构拆分时再处理不迟。*/
//						GroupsInfoCacheProvider.getInstance().remove(gid);// comment by Jack Jiang 20190228
                    } catch (Exception e) {
                        LoggerFactory.getLog().warn("发生在解散群时：", e);
                    }
                }

                return ret;
            }
            //【接口1016-24-27】创建子房间
            case ACTION_APPEND9: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                // 子房间创建者id
                String ownerUid = nwObj.getString("owner_uid");
                String ownerNickName = nwObj.getString("owner_nickname");
                //频道名称
                String nodeName = nwObj.getString("node_name");
                //子房间对应群组id
                String gid = nwObj.getString("gid");

                // 非群组不能添加子频道
                if (!groupOwnerJudge(gid, user.getUserId())) {
                    return "2";
                }

                Collection<GroupMember4Cache> allMembers =
                        GroupsMembersCacheProvider.getInstance().get(gid).values();
                createChildChanel(sqls, values, gid, ownerUid, nodeName);
                boolean update = LogicProcessor2.db.update(sqls, values, true);
                if (update) {
                    Vector<Vector<?>> vectors = db.queryData("select max(node_id) from chat_group_node where base_id='" + gid + "' and node_type='SUB_CHANNEL'");
                    // ** 【实时通知本次群内的所有人】：子频道建立成功了
                    if (!vectors.isEmpty()) {
                        ChatLogicManager4Group.batchNotification4CreateChannelAsync("创建子频道",
                                ownerUid, ownerNickName, nodeName + "(频道号:" + vectors.get(0).get(0) + ")", allMembers, gid);
                        return String.valueOf(vectors.get(0).get(0));
                    } else {
                        return "0";
                    }
                }
                return "0";
            }

            //【接口1016-24-28】进入频道(指挥员)
            case ACTION_APPEND10: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                // 子房间创建者id
                String nodeId = nwObj.getString("node_id");
                String gid = nwObj.getString("gid");
                boolean update = updateChildMemberNode(sqls, values, nodeId, gid, user);
                if (update) {
                    return "1";
                } else {
                    return "0";
                }
            }
            //【接口1016-24-29】修改频道名称
            case ACTION_APPEND11:
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                String nodeId = nwObj.getString("id");
                String name = nwObj.getString("name");
                String gid = nwObj.getString("gid");
                Collection<GroupMember4Cache> allMembers =
                        GroupsMembersCacheProvider.getInstance().get(gid).values();
                Vector<Vector<?>> vectors = db.queryData("select node_pid from chat_group_node where user_uid = '" + user.getUserId() + "' and node_type='USER' and node_pid='" + nodeId + "'");
                if (!vectors.isEmpty()) {
                    updateChildChanel(sqls, values, nodeId, name);
                    boolean update = LogicProcessor2.db.update(sqls, values, true);
                    if (update) {
                        ChatLogicManager4Group.batchNotification4CreateChannelAsync("修改子频道",
                                user.getUserId(), user.getNickname(), "频道" + nodeId + "修改名称为" + name, allMembers, gid);
                        return "1";
                    }
                } else {
                    return "2";//修改人不是频道下的成员,修改失败
                }
                return "0";
            case ACTION_APPEND13: {
                JSONObject newJson = JSONObject.parseObject(newDataJSON);
                String nid = newJson.getString("node_id");
                String groupId = newJson.getString("gid");
                // 非群组不能删除子频道
                if (!groupOwnerJudge(groupId, user.getUserId())) {
                    return "2";
                }
                deleteChildChanel(sqls, values, nid, groupId);
                boolean update = LogicProcessor2.db.update(sqls, values, false);
                if (update) {

                    // 【实时通知】：通知除群主外的所有人
                    // 从高速缓存中读取群成员列表，提升性能
                    //Collection<GroupMember4Cache> allMembersBeforeDismiss = GroupsMembersCacheProvider.getInstance().get(groupId).values();
//                        ChatLogicManager4Group.batchNotification4GroupDismissedAsync("群被解散"
//                                , allMembersBeforeDismiss, gid
//                                //							, gname
//                                , ownerUid, ownerNickname);
                    return "1";
                }
                return "0";
            }
            case ACTION_GROUP_MANAGER:
                // 设置管理员
                JSONObject newJsond = JSONObject.parseObject(newDataJSON);
                String userIdd = user.getUserId();
                String idd = newJsond.getString("id");
                String groupIdd = newJsond.getString("g_id");
                String membersd = newJsond.getString("members");

                Vector<Vector<?>> rootManager = db.queryData("select m_ids,node_id,create_user_uid from chat_group_node where g_status = 1 and node_pid is null and base_id = '" + groupIdd + "'");
                String rootMid = rootManager.get(0).get(0).toString();
                String node_id = rootManager.get(0).get(1).toString();
                String createUserUid = rootManager.get(0).get(2).toString();
                String substring = rootMid.substring(1, rootMid.lastIndexOf(","));
                boolean root = true;

                if (Objects.equals(node_id, idd) && !membersd.contains(createUserUid)) {
                    throw new EException("不能删除原始管理员【群创建者】");
                }
                if (!Objects.equals(node_id, idd)) {
                    for (String mid : substring.split(",")) {
                        if (!membersd.contains(mid)) {
                            root = false;
                        }
                    }
                }

                if (root) {
                    Vector<Vector<?>> currentUser = db.queryData("select create_user_uid from chat_group_node where node_id = '" + idd + "'");
                    if (currentUser.get(0).get(0).toString().equals(userIdd)) {
                        idsRsetOperate(membersd, idd, groupIdd, "m_ids", true, user);
                        return "1";
                    } else {
                        throw new EException("当前账号没有该操作权限,请该节点的创建者操作");
                    }
                } else {
                    throw new EException("不能删除从根节点继承的管理员，或者你可以去根节点删除");
                }
            case ACTION_GROUP_CIRCLE:
                // 划圈
                try {
                    JSONObject newJson = JSONObject.parseObject(newDataJSON);
                    String members = newJson.getString("ids");
                    if (EmptyUtils.isNotEmpty(members)) {
                        JSONArray jsonArray = JSONArray.parseArray(members);
                        StringBuilder buffer = new StringBuilder();
                        buffer.append("select count(1) from chat_group_node where c_ids != null and node_id in (");
                        for (int i = 1; i <= jsonArray.size(); i++) {
                            buffer.append("'").append(jsonArray.get(i - 1)).append("'");
                            if (i != jsonArray.size()) {
                                buffer.append(",");
                            }
                        }
                        buffer.append(")");
                        Vector<Vector<?>> count = db.queryData(buffer.toString());
                        if (count.get(0).get(0).equals("0")) {
                            String uuid = IdUtils.get8Uuid();
                            jsonArray.forEach(id -> {
                                try {
                                    Vector<Vector<?>> c = db.queryData("select c_ids from chat_group_node where node_id = '" + id + "'");
                                    if (!c.isEmpty()) {
                                        Object cId = c.get(0).get(0);
                                        if (EmptyUtils.isEmpty(cId)) {
                                            db.update(Collections.singletonList("update chat_group_node set c_ids = '," + uuid + ",' where node_id = '" + id + "'"), true);
                                        } else {
                                            String cids = cId + uuid + ",";
                                            db.update(Collections.singletonList("update chat_group_node set c_ids = '" + cids + "' where node_id = '" + id + "'"), true);
                                        }
                                    }
                                } catch (Exception e) {
                                    logger.error(e.getMessage(), e);
                                }
                            });
                            return "1";
                        }
                    }
                } catch (Exception e) {
                    logger.error("划圈失败", e);
                }

                return "0";
            case ACTION_GROUP_SUPER:
                // 设置指挥员
                try {
                    JSONObject newJson = JSONObject.parseObject(newDataJSON);
                    String id = newJson.getString("id");
                    String groupId = newJson.getString("g_id");
                    String members = newJson.getString("members");
                    Vector<Vector<?>> currentUser = db.queryData("select create_user_uid from chat_group_node where node_id = '" + id + "'");
                    List<String> currentSids = JSON.parseArray(members).stream().map(a -> JSON.parseObject(a.toString()).getString("user_uid")).collect(Collectors.toList());
                    if (currentUser.get(0).get(0).toString().equals(user.getUserId())) {
                        Vector<Vector<?>> parent = db.queryData("select node_pid from chat_group_node where g_status = 1 and base_id = '" + groupId + "' and node_type = 'MAIN_CHANNEL' and node_id = '" + id + "'");
                        if (!parent.isEmpty()) {
                            String parentNodeId = parent.get(0).get(0).toString();
                            if (EmptyUtils.isNotEmpty(parentNodeId)) {
                                Vector<Vector<?>> parentSids = db.queryData("select s_ids from chat_group_node where g_status = 1 and base_id = '" + groupId + "' and node_type = 'MAIN_CHANNEL' and node_id = '" + parentNodeId + "'");
                                Object sidParent = parentSids.get(0).get(0);
                                if (EmptyUtils.isNotEmpty(sidParent)) {
                                    String pa = sidParent.toString();
                                    List<String> parentSidList = Stream.of(pa.substring(1, pa.lastIndexOf(",")).split(",")).collect(Collectors.toList());
                                    long count = parentSidList.stream().filter(currentSids::contains).count();
                                    if (count != parentSidList.size()) {
                                        throw new EException("不能被删除父频道指定的指挥员");
                                    }
                                }
                            }
                        }

                        List<String> oldUserIds = idsRsetOperate(members, id, groupId, "s_ids", false, user);
                        try {
                            commanderIntoChannel(members, id, groupId, user);

                            notifySIdssUpdate(oldUserIds, currentSids, groupId, id);
                        } catch (Exception e) {
                            logger.error("异步推送指挥员入群失败");
                        }
                        return "1";
                    }
                } catch (Exception e) {
                    logger.error("添加指挥员失败", e);
                }
                return "0";
            case ACTION_CIRCLE_DELETE:
                // 删除圈
                JSONObject newJson = JSONObject.parseObject(newDataJSON);
                String cId = newJson.getString("c_id");
                Vector<Vector<?>> sameCidNodes = db.queryData("select node_id,c_ids from chat_group_node where c_ids like '%," + cId + ",%'");
                if (!sameCidNodes.isEmpty()) {
                    for (Vector<?> sameCidNode : sameCidNodes) {
                        String nId = sameCidNode.get(0).toString();
                        String cIds = sameCidNode.get(1).toString();
                        String res = cIds.replaceAll("," + cId, "");
                        db.update(Collections.singletonList("update chat_group_node set c_ids = " + (res.equals(",") ? null : "'" + res + "'") + " where node_id = '" + nId + "'"), true);
                    }
                    return "1";
                }
                return "0";
            default:
                throw EndsExceptionFactory.INVALID_ACTION_ID(action_id);
        }
    }

    // 通知更新指挥员
    private void notifySIdssUpdate(List<String> oldUsers, List<String> newUsers, String gid, String channelId) {
        if (!newUsers.isEmpty()) {
            try {
                List<String> deleteSusers = oldUsers.stream().filter(o -> !newUsers.contains(o)).collect(Collectors.toList());
                if (!deleteSusers.isEmpty()) {
                    String join = String.join(",", deleteSusers);
                    String selectSql = "select count(1) from chat_group_node where base_id = '" + gid + "' and node_type = 'USER'  and owner is false and user_uid in (" + join + ")";
                    Vector<Vector<?>> vectors = LogicProcessor2.db.queryData(selectSql);
                    if (!vectors.get(0).get(0).toString().equals("0")) {
                        String deleteSql = "update chat_group_node set g_status = -1 where base_id = '" + gid + "' and node_type = 'USER'  and owner is false and user_uid in (" + join + ")";
                        LogicProcessor2.db.update(Collections.singletonList(deleteSql), false);
                    }
                }
                List<String> insertSusers = newUsers.stream().filter(o -> !oldUsers.contains(o)).collect(Collectors.toList());
                if (!insertSusers.isEmpty() || !deleteSusers.isEmpty()) {
                    sendRefresh(gid, UserProtocalsType.MT78_REFRESH_SUSER);
                }

            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                e.printStackTrace();
            }
        }

    }

    private void sendRefresh(String gid, int typeu) throws Exception {
        Vector<Vector<?>> vectors = LogicProcessor2.db.queryData("select user_uid from chat_group_node where node_type = 'USER' and base_id = '" + gid + "' and g_status = 1");
        if (!vectors.isEmpty()) {
            vectors.forEach(v -> {
                String userUid = v.get(0).toString();
                try {
                    MessageHelper.sendMessage(userUid, gid, false, typeu, null);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    private List<String> idsRsetOperate(String members, String id, String groupId, String column, Boolean isManager, User user) throws Exception {
        String oldMids = "";
        Vector<Vector<?>> old = db.queryData("select " + column + " from chat_group_node where node_id = '" + id + "'");
        if (!old.isEmpty()) {
            oldMids = old.get(0).get(0).toString();
        }
        if (EmptyUtils.isNotEmpty(members) && !JSON.parseArray(members).isEmpty()) {
            String ids = "," + JSON.parseArray(members).stream().map(a -> JSON.parseObject(a.toString()).getString("user_uid")).collect(Collectors.joining(",")) + ",";
            db.update(Collections.singletonList("update chat_group_node set " + column + " = '" + ids + "' where base_id = '" + groupId + "' and node_id = '" + id + "'"), true);
            ArrayList<String> childNodeIds = new ArrayList<>();
            iterateNodeId(id, childNodeIds);
            List<String> childs = childNodeIds.stream().distinct().collect(Collectors.toList());
            for (String childId : childs) {
                Vector<Vector<?>> child = db.queryData("select " + column + " from chat_group_node where node_id = '" + childId + "'");
                if (!child.isEmpty()) {
                    String mIds = child.get(0).get(0).toString();
                    String n = ids.substring(0, ids.lastIndexOf(",")) + (EmptyUtils.isNotEmpty(mIds) ? mIds : ",");
                    String newMids = "".equals(oldMids) ? n : mIds.replaceAll(oldMids, ids);
                    String trims = newMids.substring(1, newMids.lastIndexOf(","));
                    String trimIds = Stream.of(trims.split(",")).distinct().collect(Collectors.joining(","));
                    if (EmptyUtils.isNotEmpty(trimIds)) {
                        trimIds = "," + trimIds + ",";
                    }
                    db.update(Collections.singletonList("update chat_group_node set " + column + " = '" + trimIds + "' where base_id = '" + groupId + "' and node_id = '" + childId + "'"), true);
                }
            }
            if (isManager) {
                new Thread(() -> {
                    insertManager(JSON.parseArray(members), groupId, id, user, ids);
                }).start();
            }
        } else {
            if (EmptyUtils.isNotEmpty(oldMids)) {
                db.update(Collections.singletonList("update chat_group_node set " + column + " = null where base_id = '" + groupId + "' and node_id = '" + id + "'"), true);
                ArrayList<String> childNodeIds = new ArrayList<>();
                iterateNodeId(id, childNodeIds);
                List<String> childs = childNodeIds.stream().distinct().collect(Collectors.toList());
                for (String childId : childs) {
                    Vector<Vector<?>> child = db.queryData("select " + column + " from chat_group_node where node_id = '" + childId + "'");
                    if (!child.isEmpty()) {
                        String mIds = child.get(0).get(0).toString();
                        if (mIds.equals(oldMids)) {
                            db.update(Collections.singletonList("update chat_group_node set " + column + " = null where base_id = '" + groupId + "' and node_id = '" + childId + "'"), true);
                        } else {
                            String newMids = mIds.replaceAll(oldMids, ",");
                            String trims = newMids.substring(1, newMids.lastIndexOf(","));
                            String trimIds = Stream.of(trims.split(",")).distinct().collect(Collectors.joining(","));
                            if (EmptyUtils.isNotEmpty(trimIds)) {
                                trimIds = "," + trimIds + ",";
                            }
                            db.update(Collections.singletonList("update chat_group_node set " + column + " = '" + trimIds + "' where base_id = '" + groupId + "' and node_id = '" + childId + "'"), true);
                        }
                    }
                }
            }
        }

        if (EmptyUtils.isNotEmpty(oldMids)) {
            return Stream.of(oldMids.substring(1, oldMids.lastIndexOf(",")).split(",")).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    private void insertManager(JSONArray jsonArray, String groupId, String channelId, User user, String mIds) {
        if (!jsonArray.isEmpty()) {
            jsonArray.forEach(j -> {
                try {
                    String time = DateUtil.format(new Date(), NORM_DATETIME_PATTERN);
                    String userId = JSON.parseObject(j.toString()).getString("user_uid");
                    Vector<Vector<?>> vectors = db.queryData("select count(1) from chat_group_node where g_status = 1 and user_uid = '" + userId + "' and node_type = 'USER' and base_id = '" + groupId + "'");
                    if (vectors.get(0).get(0).toString().equals("0")) {
                        Vector<Object> sqls = new Vector<>(2);
                        Vector<Object> values = new Vector<>(2);
                        sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid,node_name,create_time,create_user_uid,m_ids" +
                                ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)");
                        values.add(new Object[]{IdUtils.get8Uuid(), userId, groupId, time, user.getUserId(), time, channelId, NodeType.USER.name(), groupId, user.getNickname(), time, user.getUserId(), mIds});
                        db.update(sqls, values, false);
                    }
                } catch (Exception e) {
                    logger.error("新增管理员失败");
                }

            });
        }
    }

    private void commanderIntoChannel(String members, String id, String gid, User user) throws Exception {
        List<JSONObject> managers = JSON.parseArray(members, JSONObject.class);
        managers.forEach(manager -> {
            String time = DateUtil.format(new Date(), NORM_DATETIME_PATTERN);
            try {
                String userId = manager.getString("user_uid");
                String nickname = manager.getString("nickname");
                Vector<Vector<?>> exist = db.queryData("select count(1) from chat_group_node where node_type = 'USER' and g_status = 1 and base_id = '" + gid + "' and user_uid = '" + userId + "' and node_pid = '" + gid + "'");
                if (!exist.isEmpty()) {
                    String num = exist.get(0).get(0).toString();
                    if (Objects.equals(num, "0")) {
                        //指挥员自动入群
                        String mIds = null;
                        String sIds = null;
                        Vector<Vector<?>> parentChannel = db.queryData("select m_ids,s_ids from chat_group_node where node_id = '" + gid + "'");
                        if (!parentChannel.isEmpty()) {
                            mIds = parentChannel.get(0).get(0).toString();
                            sIds = parentChannel.get(0).get(1).toString();
                        }
                        ArrayList<String> sqls = new ArrayList<>();
                        ArrayList<Object> values = new ArrayList<>();
                        sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid,node_name,create_time,create_user_uid,m_ids,s_ids" +
                                ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
                        values.add(new Object[]{IdUtils.get8Uuid(), userId, gid, time, user.getUserId(), time, gid, NodeType.USER.name(), gid, nickname, time, user.getUserId(), mIds, sIds});
                        db.update(sqls, values, false);
                        //  inviteIntoChannel(id, user.getUserId(), userId, nickname, user.getNickname(), gid);
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }

        });
    }

    private void inviteIntoChannel(String id, String inviteUserId, String userUid, String nickname, String inviteNickName, String gid) throws Exception {
        // 更新人数
        Vector<Object> sqls = new Vector<>();
        Vector<Object> values = new Vector<>();
        prepareUpdateChannelMemberCount(sqls, values, id);
        LogicProcessor2.db.update(sqls, values, true);

        GroupEntity newGroupInfoReturn = this.queryChannelInfo(id, userUid);// 第2个参数null表示不需要取”我“在本群中的昵称，因为刚建的群还来不及设置群昵称呢
        ArrayList<GroupMemberEntity> newJoinedMemberList = new ArrayList<>();
        Collection<GroupMember4Cache> oldMemberList = GroupsMembersCacheProvider.getInstance().get(gid + "_" + id).values();
        GroupMemberEntity groupMemberEntity = new GroupMemberEntity();
        groupMemberEntity.setUser_uid(userUid);
        groupMemberEntity.setNickname(nickname);
        groupMemberEntity.setG_id(gid);
        newJoinedMemberList.add(groupMemberEntity);
        inviteNotify(gid, inviteUserId, inviteNickName, "0", newJoinedMemberList, oldMemberList, newGroupInfoReturn, id);
        // ** 【高速缓存】：即时更新群缓存数据（因为新建了此群）
        GroupsInfoCacheProvider.getInstance().reloadOneFromDB(gid + "_" + id);
    }

    private void clikOutoChannle(String channelId, User user, ArrayList<GroupMemberEntity> membersBeDeleteList, String gId) {
        try {
            // 更新群成员人数
            Vector<Object> sqls = new Vector<>();
            Vector<Object> values = new Vector<>();
            prepareUpdateChannelMemberCount(sqls, values, channelId);
            LogicProcessor2.db.update(sqls, values, true);

            GroupsMembersCacheProvider.getInstance().reloadOneFromDB(gId + "_" + channelId);
            // 【实时通知】：通知此次被删除的人、通知群里的其他余下的人
            ChatLogicManager4Group.batchNotification4SomeoneBeRemovedAsync(
                    "删除群员", user.getUserId(), user.getNickname()
                    , membersBeDeleteList
                    , GroupsMembersCacheProvider.getInstance().get(gId + "_" + channelId).values()
                    , gId + "_" + channelId
            );
        } catch (Exception e) {
            logger.error("从频道踢人失败", e);
        }
    }

    private void iterateNodeId(String nodePid, List<String> list) throws Exception {
        Vector<Vector<?>> vectors = db.queryData("select node_id from chat_group_node where node_pid = '" + nodePid + "'");
        if (!vectors.isEmpty()) {
            list.addAll(vectors.stream().map(a -> a.get(0).toString()).collect(Collectors.toList()));
            for (Vector<?> vector : vectors) {
                String nodeId = vector.get(0).toString();
                iterateNodeId(nodeId, list);
            }
        }
    }

    private void iterateUserId(String nodePid, List<String> list) throws Exception {
        Vector<Vector<?>> vectors = db.queryData("select node_id from chat_group_node where node_type = 'USER' and g_status = 1 and node_pid = '" + nodePid + "'");
        if (!vectors.isEmpty()) {
            list.addAll(vectors.stream().map(a -> a.get(0).toString()).collect(Collectors.toList()));
            for (Vector<?> vector : vectors) {
                String nodeId = vector.get(0).toString();
                iterateNodeId(nodeId, list);
            }
        }
    }

    private void iterateNode(String nodePid, List<String> list) throws Exception {
        Vector<Vector<?>> vectors = db.queryData("select node_id from chat_group_node where node_type = 'MAIN_CHANNEL' and node_pid = '" + nodePid + "'");
        if (!vectors.isEmpty()) {
            list.addAll(vectors.stream().map(a -> a.get(0).toString()).collect(Collectors.toList()));
            for (Vector<?> vector : vectors) {
                String nodeId = vector.get(0).toString();
                iterateNodeId(nodeId, list);
            }
        }
    }

    private void inviteNotify(String gid, String inviteUid, String inviteNickName, String srcFrom, ArrayList<GroupMemberEntity> newJoinedMemberList,
                              Collection<GroupMember4Cache> oldMemberList, GroupEntity groupEntity, String pid) throws Exception {
        // 【实时通知】：通知新加入的人（“他”加群成功）和老群员（有人加群了）
        groupEntity.setG_id(gid + "_" + pid);
        ChatLogicManager4Group.batchNotification4InviteMembersAsync(
                srcFrom
                , "群聊CMD-邀请通知"
                , inviteUid, inviteNickName
                , newJoinedMemberList
                , oldMemberList
                , groupEntity);

        // ** 【高速缓存】：将最新群成员数据更新到高速缓存中（以便后绪使用）
        // TODO: 未来优化空间：直接用新进成员集合，可节省一次db查询，暂时可先不折腾
        GroupsMembersCacheProvider.getInstance().reloadOneFromDB(gid + "_" + pid);

    }

    private Boolean groupOwnerJudge(String gid, String userId) throws Exception {
        Vector<Vector<?>> vs = db.queryData("select g_id from chat_group_base where create_user_uid = '" + userId + "'");
        if (!vs.isEmpty()) {
            for (Vector<?> vector : vs) {
                if (Objects.equals(vector.get(0), gid)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 维护群组信息查询管理.
     *
     * @param action_id   维护类型，SysConstant中的操作类型常量
     * @param newDataJSON 客端发送过来的本次修改新数据(可能为空，理论上与oldData不会同时空）
     * @param oldData     客端发送过来的本次修改前的老数据(可能为空，理论上与newData不会同时空）
     * @param user        操作者的用户名
     * @return 返回给客户端的对象
     */
    public String maintainMgrGroupQueryJobDispatcher(int action_id, String newDataJSON, Object oldData, User user) throws
            Exception {

        switch (action_id) {
            // 【接口1016-25-7】获取用户群列表的接口
            case ACTION_APPEND1: {
                // 客户端传过来的是UID
                // 该用户的好友群列表
                ArrayList<GroupEntity> groupsToClient = queryGroupInfoList(newDataJSON);

                return JSON.toJSONString(groupsToClient);
            }
            // 【接口1016-25-8】查询群基本信息
            case ACTION_APPEND2: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);

                // 查询的群id
                String gid = nwObj.getString("gid");
                // 非必须参数，如果本参数不为空，则表示要同时把”我“在该群中的昵称给查出来，否则不需要查
                String myUserId = nwObj.getString("my_user_id");

                return JSON.toJSONString(queryGroupInfo(gid, myUserId));
            }
            // 【接口1016-25-62】查询频道基本信息
            case ACTION_CHANNEL_DETAIL: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);

                // 查询的群id
                String channelId = nwObj.getString("channel_id");
                // 非必须参数，如果本参数不为空，则表示要同时把”我“在该群中的昵称给查出来，否则不需要查

                return JSON.toJSONString(queryChannelInfo(channelId, user.getUserId()));
            }
            // 【接口1016-25-9】查询群成员列表（含成员基本信息）
            case ACTION_APPEND3: {
                // 查询的群id
                return JSON.toJSONString(queryGroupMemberList(newDataJSON));
            }
            case ACTION_QUERY_USERS_OF_GROUP: {
                return JSON.toJSONString(queryGroupMembers(newDataJSON));
            }
            //【接口1016-25-22】获取群频道列表
            case ACTION_APPEND4: {
                return JSON.toJSONString(queryChannel(newDataJSON, user));
            }
            //【接口1016-25-23】查询指定群组的某个频道成员列表
            case ACTION_APPEND5: {
                return JSON.toJSONString(queryChannelMemberList2(newDataJSON, user));
            }
            //【接口1016-25-24】获取当前对讲频道
            case ACTION_APPEND6: {
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                // 查询的群id
                String gid = nwObj.getString("gid");
                // 非必须参数，如果本参数不为空，则表示要同时把”我“在该群中的昵称给查出来，否则不需要查
                String user_uid = nwObj.getString("user_uid");
                return queryChannelForUser(gid, user_uid);
            }
            //【接口1016-25-25】获取云盘文件列表
            case ACTION_APPEND7:
                JSONObject nwObj = JSONObject.parseObject(newDataJSON);
                String gid = nwObj.getString("gid");
                Integer type = nwObj.getInteger("type");
                String startTime = nwObj.getString("start_time");
                String endTime = nwObj.getString("end_time");
                Integer pageNumber = nwObj.getIntValue("page_number");
                Integer pageSize = nwObj.getInteger("page_size");
                String uid = nwObj.getString("uid");
                Integer storeType = nwObj.getInteger("store_type");
                return queryCloudFileByGroup(gid, type, startTime, endTime, pageNumber, pageSize, uid, storeType);
            // 查询群组树
            case ACTION_GROUP_TREE:
                ChannelTree channelTree = new ChannelTree();
                String groupId = JSONObject.parseObject(newDataJSON).getString("gid");
                String userId = user.getUserId();
                Vector<Vector<?>> exist = db.queryData("select count(1) from chat_group_node where base_id = '" + groupId + "' and g_status = 1 and m_ids like '%," + userId + ",%'");
                boolean android = user.getAndroid() || (!exist.isEmpty() && exist.get(0).get(0).toString().equals("0"));
                String sql;
                if (!android) {
                    sql = "select node_pid,m_ids from chat_group_node where m_ids like '%," + userId + ",%' and base_id = '" + groupId + "' order by create_time asc limit 0,1";
                } else {
                    sql = "select node_pid,m_ids from chat_group_node where node_pid is null and base_id = '" + groupId + "' ";
                }
                Vector<Vector<?>> vectors = db.queryData(sql);
                if (!vectors.isEmpty()) {
                    Object pid = vectors.get(0).get(0);
                    String mids = vectors.get(0).get(1).toString();
                    String loginId = android ? mids.substring(1, mids.lastIndexOf(",")) : userId;
                    String parentId = Objects.equals(pid, "") || Objects.isNull(pid) ? null : pid.toString();
                    buildTree(loginId, groupId, parentId, channelTree, 1, false);
                }
                return JSON.toJSONString(channelTree);
            // 查询管理员指挥员列表
            case ACTION_MANAGER_LIST:
                JSONObject jsonObject = JSONObject.parseObject(newDataJSON);
                String g_id = jsonObject.getString("gid");
                String userType = jsonObject.getString("user_type");//0-管理员,1-指挥员
                Vector<Vector<?>> res = db.queryData("select " + (Objects.equals(userType, "0") ? "m_ids" : "s_ids") + " from chat_group_node where  base_id = " + g_id);
                List<String> existIds = new ArrayList<>();
                if (!res.isEmpty()) {
                    res.forEach(id_s -> {
                        Object e = id_s.get(0);
                        if (EmptyUtils.isNotEmpty(e)) {
                            String ids = e.toString();
                            String result = ids.substring(1, ids.lastIndexOf(","));
                            existIds.addAll(Stream.of(result.split(",")).collect(Collectors.toList()));
                        }
                    });
                }

                Vector<Vector<?>> result = db.queryData("select user_uid,nickname,user_mail from g_users  where del_flag = 0 and account_type = 1 ");
                ArrayList<UserInfoVO> list = new ArrayList<>();
                if (!result.isEmpty()) {
                    result.forEach(m -> {
                        String user_id = m.get(0).toString();
                        if (!existIds.contains(user_id)) {
                            UserInfoVO use = new UserInfoVO();
                            use.setUserUid(user_id);
                            use.setNickname(m.get(1).toString());
                            use.setUserMail(m.get(2).toString());
                            list.add(use);
                        }
                    });
                }

                return JSON.toJSONString(list);
            case ACTION_LOGIN_USER_JUDGE_ZHIHUI:
                JSONObject json = JSONObject.parseObject(newDataJSON);
                String g = json.getString("gid");
                Vector<Vector<?>> vector = db.queryData("select count(1) from chat_group_node where base_id = " + g + " and s_ids like '%," + user.getUserId() + ",%'");
                return JSON.toJSONString(!vector.isEmpty() && !vector.get(0).get(0).toString().equals("0") ? 1 : 0);
            case ACTION_LIST_CIRCLE:
                JSONObject param = JSONObject.parseObject(newDataJSON);
                String group = param.getString("gid");
                String channelId = param.getString("id");
                HashMap<String, List<ChannelEntity>> map = new HashMap<>();
                Vector<Vector<?>> cicles = db.queryData("select c_ids,node_id,node_name from chat_group_node where c_ids is not null and base_id = '" + group + "' and g_status = 1 and node_pid = '" + channelId + "' and node_type = 'MAIN_CHANNEL'");
                if (!cicles.isEmpty()) {
                    cicles.forEach(vec -> {
                        String cIds = vec.get(0).toString();
                        ChannelEntity channelEntity = new ChannelEntity();
                        channelEntity.setNodeId(vec.get(1).toString());
                        channelEntity.setNodeName(vec.get(2).toString());
                        List<String> cs = Stream.of(cIds.split(",")).filter(EmptyUtils::isNotEmpty).collect(Collectors.toList());
                        cs.forEach(i -> {
                            if (map.containsKey(i)) {
                                List<ChannelEntity> channelEntities = map.get(i);
                                channelEntities.add(channelEntity);
                            } else {
                                ArrayList<ChannelEntity> entities = new ArrayList<>();
                                entities.add(channelEntity);
                                map.put(i, entities);
                            }
                        });
                    });
                }
                ArrayList<CircleChannel> objects = new ArrayList<>();
                for (Map.Entry<String, List<ChannelEntity>> entry : map.entrySet()) {
                    CircleChannel circleChannel = new CircleChannel();
                    circleChannel.setCid(entry.getKey());
                    circleChannel.setChannels(entry.getValue());
                    objects.add(circleChannel);
                }
                return JSON.toJSONString(objects);
            case ACTION_USER_IN_CHANNEL:
                // 某个账号是否在频道里面
                JSONObject jo = JSONObject.parseObject(newDataJSON);
                String id = jo.getString("id");
                Vector<Vector<?>> exists = db.queryData("select count(1) from chat_group_node where g_status = 1 and node_pid = '" + id + "' and node_type = 'USER' and user_uid = '" + user.getUserId() + "'");
                return JSON.toJSONString(exists.get(0).get(0).toString().equals("0") ? "0" : "1");

            case ACTION_QUERY_MANAGER_LIST:
                JSONObject jsonObject2 = JSONObject.parseObject(newDataJSON);
                String g_id2 = jsonObject2.getString("gid");
                String userType2 = jsonObject2.getString("user_type");//0-管理员,1-指挥员
                String nodeId = jsonObject2.getString("node_id");
                Vector<Vector<?>> response = db.queryData("select node_pid from chat_group_node where node_id = '" + nodeId + "' and node_type = 'MAIN_CHANNEL' and g_status = 1");
                List<String> pExistIds = new ArrayList<>();
                if (!response.isEmpty()) {
                    String pId = response.get(0).get(0).toString();
                    if (EmptyUtils.isNotEmpty(pId)) {
                        Vector<Vector<?>> pIds = db.queryData("select " + (Objects.equals(userType2, "0") ? "m_ids" : "s_ids") + " from chat_group_node where  base_id = '" + g_id2 + "' and node_id = '" + pId + "'");
                        if (!pIds.isEmpty()) {
                            String pIdstring = pIds.get(0).get(0).toString();
                            if (EmptyUtils.isNotEmpty(pIdstring)) {
                                String result2 = pIdstring.substring(1, pIdstring.lastIndexOf(","));
                                pExistIds.addAll(Stream.of(result2.split(",")).collect(Collectors.toList()));
                            }
                        }
                    }
                }
                Vector<Vector<?>> res2 = db.queryData("select " + (Objects.equals(userType2, "0") ? "m_ids" : "s_ids") + " from chat_group_node where  base_id = '" + g_id2 + "' and node_id = '" + nodeId + "'");
                List<String> existIds2 = new ArrayList<>();
                if (!res2.isEmpty()) {
                    String ids = res2.get(0).get(0).toString();
                    if (EmptyUtils.isNotEmpty(ids)) {
                        String result2 = ids.substring(1, ids.lastIndexOf(","));
                        existIds2.addAll(Stream.of(result2.split(",")).filter(i -> !pExistIds.contains(i)).collect(Collectors.toList()));
                    }
                }
                Vector<Vector<?>> result2 = db.queryData(queryUserInfoById(user.getUserId()));
                ArrayList<UserInfoVO> list2 = new ArrayList<>();
                if (!result2.isEmpty()) {
                    result2.forEach(m -> {
                        String user_id = m.get(0).toString();
                        UserInfoVO use = new UserInfoVO();
                        use.setUserUid(user_id);
                        use.setNickname(m.get(1).toString());
                        use.setUserMail(m.get(2).toString());
                        use.setFromWhere(pExistIds.contains(user_id) ? 0 : existIds2.contains(user_id) ? 1 : 2);
                        list2.add(use);
                    });
                }
                return JSON.toJSONString(list2);
            case ACTION_GET_DEVICE_UNIQE_GROUP_CHANNEL:
                String userUid = user.getUserId();
                Vector<Vector<?>> vres = db.queryData("select c.base_id,c.node_pid,c.node_id from chat_group_node c left join g_users g on  g.user_uid = c.user_uid" +
                        " where c.node_type = 'USER' and c.g_status = 1 and g.del_flag = 0 and g.user_type = 1 and c.user_uid = '" + userUid + "'");
                JSONObject object = new JSONObject();
                object.put("groupId", vres.get(0).get(0).toString());
                object.put("channelId", vres.get(0).get(1).toString());
                object.put("nodeId", vres.get(0).get(2).toString());
                return object.toJSONString();
            case ACTION_GET_DEVICE_CONFIG_LIST:
                JSONObject ob = JSONObject.parseObject(newDataJSON);
                String dev = ob.getString("userUid");
                return RedisUtil.get("device:support:config:" + dev);
            case ACTION_GET_CURRENT_CONFIG:
                JSONObject currentDevice = JSONObject.parseObject(newDataJSON);
                String deviceUid = currentDevice.getString("userUid");
                return RedisUtil.get("device:current:config:" + deviceUid);
            case ACTION_SET_DEVICE_CONFIG:
                JSONObject current = JSONObject.parseObject(newDataJSON);
                String mess = current.getString("message");
                String user_uid = current.getString("userUid");
                MessageHelper.processMT81_SET_DEVICE_CONFIG(user_uid, mess, null);
                return "1";
            case ACTION_UPLOAD_DEVICE_CONFIG_LIST:
                JSONObject objec = JSON.parseObject(newDataJSON);
                JSONObject config = objec.getJSONObject("config");
                String serialno = objec.getJSONObject("basic").getString("serialno");
                RedisUtil.set("device:support:config:" + serialno, objec.toJSONString());
                RedisUtil.set("device:current:config:" + serialno, config.toJSONString());
                return "1";
            case ACTION_UPLOAD_CURRENT_CONFIG:
                JSONObject ect = JSON.parseObject(newDataJSON);
                ect = ect.containsKey("config") ? ect.getJSONObject("config") : ect;
                RedisUtil.set("device:current:config:" + user.getUserId(), ect.toJSONString());
                return "1";
            case ACTION_DEVICE_OPEN_GPS:
                JSONObject gps = JSON.parseObject(newDataJSON);
                String gpsUid = gps.getString("userUid");
                MessageHelper.processMT83_DEVICE_OPEN_GPS(gpsUid, null, null);
                return "1";
            case ACTION_DEVICE_CLOSE_GPS:
                JSONObject closeGps = JSON.parseObject(newDataJSON);
                String closeGpsUid = closeGps.getString("userUid");
                MessageHelper.processMT84_DEVICE_CLOSE_GPS(closeGpsUid, null, null);
                return "1";
            case ACTION_GET_THIRD_DEVICE_STREAM_URL:
                JSONObject js = JSONObject.parseObject(newDataJSON);
                String devId = js.getString("id");
                return JSON.toJSONString("rtmp://" + BaseConf.getInstance().getMEDIA_SERVER_IP() + "/live/device-" + devId);
            default:
                throw EndsExceptionFactory.INVALID_ACTION_ID(action_id);
        }
    }

    public String queryUserInfoById(String userId) throws Exception {
        String sql = "select user_uid,nickname,user_mail from g_users where del_flag = 0 and user_uid in " +
                "(select user_id from structure_user_info where structure_no in " +
                "(select structure_no from structure_info where structure_level " +
                "like concat ('%',(select structure_no from structure_user_info " +
                "where user_id='" + userId + "' and user_type='" + CaseUserType.USER.name() + "'),'%'))) " +
                "and user_type='" + CaseUserType.USER.name() + "'";

        return sql;
    }

    private List<UserInfoDTO> iterateManagersByCurrentUser(String userId, String groupId, String channelId) {
        List<UserInfoDTO> list = new ArrayList<>();
        try {
            Vector<Vector<?>> vectors = db.queryData("select m_ids from chat_group_node where g_status = 1 and node_pid = '" + channelId + "' and base_id = '" + groupId + "' and node_type = 'USER' and user_uid = '" + userId + "'");
            if (!vectors.isEmpty()) {
                Object res = vectors.get(0).get(0);
                if (EmptyUtils.isNotEmpty(res)) {
                    String ids = res.toString().substring(1, res.toString().lastIndexOf(","));
                    String id = Stream.of(ids.split(",")).filter(EmptyUtils::isNotEmpty).collect(Collectors.joining("','"));
                    Vector<Vector<?>> managers = db.queryData("select user_uid,nickname from g_users where del_flag = 0 and user_uid in ('" + id + "')");
                    managers.forEach(a -> {
                        UserInfoDTO user = new UserInfoDTO();
                        user.setUserUid(a.get(0).toString());
                        user.setNickname(a.get(1).toString());
                        list.add(user);
                    });
                }
            }
        } catch (Exception e) {
            logger.error("查询管理员列表失败", e);
        }
        return list;

    }

    private void buildTree(String userId, String groupId, String parentId, ChannelTree channelTree, Integer type, Boolean loop) {
        try {
            if (type == 1) {
                Vector<Vector<?>> channels = db.queryData("select node_id,node_pid,m_ids,node_name,s_ids,have_child,c_ids  from chat_group_node where node_type = 'MAIN_CHANNEL' and g_status = 1 and  base_id = '" + groupId + "' and node_pid " + (null == parentId ? " is null " : " = '" + parentId + "'") + " and m_ids like '%," + userId + ",%' order by create_time asc");
                if (!channels.isEmpty()) {
                    List<ChannelTree> channelTrees = null == parentId ? null : channelTree.getChild() == null ? new ArrayList<>() : channelTree.getChild();
                    for (Vector<?> channel : channels) {
                        int i = 0;
                        ChannelTree channelNode;
                        if (!loop) {
                            channelNode = channelTree;
                        } else {
                            channelNode = new ChannelTree();
                            channelTrees.add(channelNode);
                            channelTree.setChild(channelTrees);
                        }
                        channelNode.setId(channel.get(i++).toString());
                        Object pId = channel.get(i++);
                        String mIds = channel.get(i++).toString();
                        channelNode.setName(channel.get(i++).toString());
                        String sIds = channel.get(i++).toString();
                        String haveChild = channel.get(i++).toString();
                        String cIds = channel.get(i).toString();
                        channelNode.setgId(groupId);
                        channelNode.setType("1");
                        channelNode.setpId(pId.toString());
                        channelNode.setpType("1");
                        fillIds(channelNode, mIds, sIds, cIds);
                        buildTree(userId, groupId, channelNode.getId(), channelNode, 2, true);
                        buildTree(userId, groupId, channelNode.getId(), channelNode, 1, true);
                    }
                }
            }
            if (type == 2) {
                Vector<Vector<?>> users = db.queryData("select a.user_uid,n.m_ids,n.s_ids,a.nickname from g_users a left join chat_group_node n " +
                        "on a.user_uid = n.user_uid  where n.g_status = 1 and a.del_flag is false and n.base_id = '" + groupId + "' and n.node_pid = '" + parentId + "' and n.node_type = 'USER'");
                if (!users.isEmpty()) {
                    if (channelTree.getChild() == null) {
                        channelTree.setChild(new ArrayList<>());
                    }
                    for (Vector<?> user : users) {
                        int i = 0;
                        ChannelTree userNode = new ChannelTree();
                        userNode.setId(user.get(i++).toString());
                        String mIds = user.get(i++).toString();
                        String sIds = user.get(i++).toString();
                        userNode.setName(user.get(i).toString());
                        userNode.setgId(groupId);
                        userNode.setType("2");
                        userNode.setpId(parentId);
                        userNode.setpType("1");
                        fillIds(userNode, mIds, sIds, null);
                        channelTree.getChild().add(userNode);
                    }
                }
            }
        } catch (
                Exception e) {
            logger.error("buildTree:" + e.getMessage(), e);
        }

    }

    private void fillIds(ChannelTree channelNode, String mIds, String sIds, String cIds) {
        List<UserInfoDTO> mUsers = userListFill(mIds);
        channelNode.setmUsers(mUsers);
        List<UserInfoDTO> sUsers = userListFill(sIds);
        channelNode.setsUsers(sUsers);
        if (EmptyUtils.isNotEmpty(cIds)) {
            String ids = cIds.substring(1, cIds.lastIndexOf(","));
            channelNode.setcIds(Stream.of(ids.split(",")).collect(Collectors.toList()));
        } else {
            channelNode.setcIds(new ArrayList<>());
        }
    }

    private List<UserInfoDTO> userListFill(String idStr) {
        List<UserInfoDTO> sUser = new ArrayList<>();
        if (EmptyUtils.isNotEmpty(idStr)) {
            String ids = idStr.substring(1, idStr.lastIndexOf(","));
            List<String> sidList = Stream.of(ids.split(",")).collect(Collectors.toList());
            sidList.forEach(id -> {
                try {
                    if (EmptyUtils.isNotEmpty(id)) {
                        Vector<Vector<?>> vectors = db.queryData("select nickname  from g_users where  user_uid = '" + id + "'");
                        if (!vectors.isEmpty()) {
                            UserInfoDTO user = new UserInfoDTO();
                            user.setNickname(vectors.get(0).get(0).toString());
                            user.setUserUid(id);
                            sUser.add(user);
                        }
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            });
        }
        return sUser;
    }

    private String constructNewGroupName(ArrayList<GroupMemberEntity> members) {
        if (!members.isEmpty()) {
            String name = "";

            int cnt = 0;
            for (int i = members.size() - 1; i >= 0; i--) {
                name += (cnt == 0 ? "" : "、") + members.get(i).getNickname();
                cnt += 1;

                // 最多只合成3个人的昵称作为群名
                if (cnt >= 3)
                    break;
            }

            System.out.println("【截断前】生成完成的群聊名称：" + name);
            name = CommonUtils.truncString(name, GROUP_NAME_MAX_LENGTH, "...");
            System.out.println("【截断后】生成完成的群聊名称：" + name);

            return name + "等";
        }

        return "未命名的群聊";
    }

    /**
     * 查询指定群组的群成员列表。
     * <p>
     * <b>注意：</b>如果用于大量频繁读取且只需要群成员id的场景下，请使用
     * {@link GroupsMembersCacheProvider#get(String)}缓存，从而提升性能，
     * 防止频繁读取DB这种慢IO拖慢系统性能且有可能导致DB瓶颈。
     * SQL: select 	a.user_uid 	,a.base_id 	,a.node_id 	,a.node_pid   ,a.node_type	,IFNULL(a.nickname_ingroup,b.nickname) as nname
     * ,b.user_avatar_file_name  FROM (	select user_uid,base_id,nickname_ingroup,node_id,node_pid,node_type from chat_group_node where g_status = 1 and node_pid ='null'  and node_type='USER') a left join g_users b on a.user_uid = b.user_uid where EXISTS (select 1 from chat_group_base c where a.base_id = c.g_id and c.g_status=1)
     *
     * @see GroupsMembersCacheProvider#get(String)
     */
    public static <T extends GroupMember4Cache> ArrayList<T> queryGroupMemberList(String gid) throws Exception {
        String nodeId = null;
        if (gid.contains("_")) {
            String[] split = gid.split("_");
            gid = split[0];
            nodeId = split[1];
        }
        StringBuilder sb = new StringBuilder()
                .append("select ")
                .append("	a.user_uid ")
                .append("	,a.base_id ")
                .append("	,a.node_id ").append("	,a.node_pid ").append("  ,a.node_type")
                .append("	," + DBDepend.getNVLFunc("a.nickname_ingroup", "b.nickname") + " as nname ")
                .append("	,b.user_avatar_file_name ")
                .append(" FROM ")
                .append("(")
                // 使用子查询提升查询性能
                .append("	select user_uid,base_id,nickname_ingroup,node_id,node_pid,node_type from chat_group_node where g_status = 1 and base_id = '" + gid + "' ")
                .append(" and node_type='" + NodeType.USER.name() + "' ");
        if (EmptyUtils.isNotEmpty(nodeId)) {
            sb.append(" and node_pid= '" + nodeId + "' ");
        }
        sb.append(") a ")
                .append("left join g_users b on a.user_uid = b.user_uid ")
                // 本条件将限制只能查到正常状态下的群成员列表（使用EXISTS语句作为条件是为了提升查询性能）
                .append("where EXISTS (select 1 from chat_group_base c where a.base_id = c.g_id and c.g_status=1) ");

        LoggerFactory.getLog().info("############################################################# queryGroupMemberList:" + sb);

        // 群员列表数据库行数据
        Vector<Vector<?>> members = db.queryData(sb.toString());
        ArrayList<GroupMember4Cache> membersToClient = new ArrayList<GroupMember4Cache>();
        // 遍历行数据，组装成对象List
        for (Vector<?> row : members) {
            GroupMemberEntity gme = new GroupMemberEntity();
            int i = 0;
            gme.setUser_uid((String) row.get(i++));
            gme.setG_id((String) row.get(i++));
            gme.setNode_id((row.get(i++)).toString());
            gme.setNode_pid((row.get(i++)).toString());
            gme.setNode_type((String) row.get(i++));
            gme.setNickname((String) row.get(i++));
            gme.setUserAvatarFileName((String) row.get(i++));
            membersToClient.add(gme);
        }

        return (ArrayList<T>) membersToClient;
    }

    public static <T extends GroupMember4Cache> ArrayList<T> queryGroupMembers(String gid) throws Exception {
        if (gid.contains("_")) {
            String[] split = gid.split("_");
            gid = split[0];
        }
        // 使用子查询提升查询性能
        StringBuilder sb = new StringBuilder()
                .append("select ")
                .append("a.user_uid, ")
                .append("b.nickname ")
                .append(" FROM ")
                .append("(").append("	select DISTINCT(user_uid)  from chat_group_node where g_status = 1 and base_id = '").append(gid).append("' ").append(" and node_type='").append(NodeType.USER.name()).append("' ");
        sb.append(") a ")
                .append("left join g_users b on a.user_uid = b.user_uid  where b.del_flag is false ");
        // 本条件将限制只能查到正常状态下的群成员列表（使用EXISTS语句作为条件是为了提升查询性能）
        Vector<Vector<?>> members = db.queryData(sb.toString());
        ArrayList<GroupMember4Cache> membersToClient = new ArrayList<>();
        // 遍历行数据，组装成对象List
        for (Vector<?> row : members) {
            GroupMemberEntity gme = new GroupMemberEntity();
            int i = 0;
            gme.setUser_uid((String) row.get(i++));
            gme.setNickname((String) row.get(i));
            membersToClient.add(gme);
        }

        return (ArrayList<T>) membersToClient;
    }


    /**
     * 查询指定用户的所有群列表。
     * <p>
     * 注意：本方法中的sql查询字段个数、顺序，必须与解析方法 {@link #constructGroupEntityFromQueryRow(Vector)}
     * 保持一致，否则无法完成从数据库原始行数据到 GroupEntity 对象的转换！
     *
     * @param uid 被查询的用户id
     */
    private ArrayList<GroupEntity> queryGroupInfoList(String uid) throws Exception {
        StringBuilder sb = new StringBuilder();
        // 查询指定用户的群列表
        sb.append("select ")
                .append("	 a.base_id")              // 群id
                .append("	,b.g_status")         // 群状态
                .append("	,b.g_name")           // 群名称
                .append("	,b.g_owner_user_uid") // 群主uid
                .append("	,b.g_notice")         // 群公告
//			.append("	,b.msg_no_promt" )     // 免打扰状态
                .append("	,b.max_member_count") // 允许的最大群员数
                .append("	,b.g_member_count")   // 当前总群员数
                .append("	,c.nickname ")        // 群主昵称
                // .append("	,a.nickname_ingroup ")// "我"在本群的昵称

                .append("	,b.g_notice_updatetime ")// 群公告更新时间
                .append("	,b.g_notice_updateuid ") // 群公告更新者
                .append("	,d.nickname as nickname_ingroup ")   // 群公告更新者昵称
                .append("	,b.create_time ")        // 群创建时间
                .append("	,1 as isInGroup ")       // ”我“是否在此群中（既然是查我的群列表，那肯定在了，加此字段是为了与 queryGroupInfo()方法中的查询保持一致
                .append("	,e.nickname as create_user_name ")
                .append("   ,b.create_user_uid ")// 群创建者昵称
                .append("from ")
                .append("( ")
                .append("	select distinct(base_id) as base_id" +
                        "	from chat_group_node where g_status = 1 and user_uid ='" + uid + "'")
                .append(")a  ")
                // 注意：g_status=1表示此群当前是有效的（另外的状态是删除或被封禁，就不需要返回给用户了）
                .append("left join chat_group_base b on a.base_id = b.g_id and b.g_status = 1 ")
                .append("left join g_users c on b.g_owner_user_uid = c.user_uid ")
                .append("left join g_users d on b.g_notice_updateuid = d.user_uid ")
                .append("left join g_users e on b.create_user_uid = e.user_uid ")
                .append("order by b.create_time desc ");
        ;

        // 该用户的好友群列表
        Vector<Vector<?>> groups = db.queryData(sb.toString());
        ArrayList<GroupEntity> groupsToClient = new ArrayList<GroupEntity>();
        // 遍历群信息列表，组装成对象List
        for (Vector<?> row : groups) {
            groupsToClient.add(constructChannelEntityFromQueryRow(row));
        }

        return groupsToClient;
    }

    /**
     * 查询指定群的基本信息。
     * <p>
     * 注意：本方法中的sql查询字段个数、顺序，必须与解析方法 {@link #constructGroupEntityFromQueryRow(Vector)}
     * 保持一致，否则无法完成从数据库原始行数据到 GroupEntity 对象的转换！
     *
     * @param gid      要查询的群id
     * @param myUserId 非必须参数，如果本参数不为空则表示要同时把”我“在该群中的昵称等给查出来，否则不需要查（表示普通的查询群信息）
     */
    private GroupEntity queryGroupInfo(String gid, String myUserId) throws Exception {
        // 是否需要取出”我“在该群中的信息（比如：群内昵称、我是否在此群中）
        boolean needGetMyselfInfo = !CommonUtils.isStringEmpty(myUserId);

        // 取出”我“在群里的昵称子查询
        String nickname_ingroup_SQLFeild = ",(select nickname_ingroup from chat_group_node " +
                "	where base_id ='" + gid + "' and user_uid='" + myUserId + "') as nickname_ingroup ";
        // 取出”我“是否在此群里的子查询（存在则返回1，不存在则返回0，返回-1表示不需要查询此值）
        String im_in_group_SQLField = ", IF((SELECT count(1) FROM chat_group_node WHERE base_id = '" + gid + "' AND user_uid = '" + myUserId + "' AND g_status = 1 and node_type = 'USER' ) > 0,1,0) AS isInGroup ";

        StringBuilder sb = new StringBuilder();
        sb.append("select b.g_id")           // 群id
                .append("	,b.g_status")        // 群状态
                .append("	,b.g_name")          // 群名称
                .append("	,b.g_owner_user_uid")// 群主uid
                .append("	,b.g_notice")        // 群公告
//			.append("	,b.msg_no_promt")    // 免打扰状态
                .append("	,b.max_member_count")// 允许的最大群员数
                .append("	,b.g_member_count ") // 当前总群员数
                .append("	,null as nickname ")       // 群主昵称
                // "我"在本群的昵称
                .append("	,null as  nickname_ingroup ")

                .append("	,b.g_notice_updatetime ")// 群公告更新时间
                .append("	,b.g_notice_updateuid ") // 群公告更新者
                .append("	,null as nickname_ingroup ")   // 群公告更新者昵称
                .append("	,b.create_time ")        // 群创建时间
                // 取出”我“是否在此群里的子查询（存在则返回1，不存在则返回0，返回-1表示不需要查询此值）
                .append(needGetMyselfInfo ? im_in_group_SQLField : ",-1 as isInGroup ")
                .append("	,null as create_user_name ")    // 群创建者昵称
                .append("from ")
                .append("(")
                .append("	select * from chat_group_base where g_id='" + gid + "' and g_status=1 ")
                .append(")b ");


        Vector<Vector<?>> vv = db.queryData(sb.toString());
        if (!vv.isEmpty())
            return constructGroupEntityFromQueryRow(vv.get(0));

        return null;
    }


    /**
     * 查询指定群的基本信息。
     * <p>
     * 注意：本方法中的sql查询字段个数、顺序，必须与解析方法 {@link #constructGroupEntityFromQueryRow(Vector)}
     * 保持一致，否则无法完成从数据库原始行数据到 GroupEntity 对象的转换！
     *
     * @param myUserId 非必须参数，如果本参数不为空则表示要同时把”我“在该群中的昵称等给查出来，否则不需要查（表示普通的查询群信息）
     * @return
     * @throws Exception
     * @see {@link #constructGroupEntityFromQueryRow(Vector)}
     */
    private GroupEntity queryChannelInfo(String channelId, String myUserId) throws Exception {
        // 是否需要取出”我“在该群中的信息（比如：群内昵称、我是否在此群中）
        boolean needGetMyselfInfo = !CommonUtils.isStringEmpty(myUserId);

        // 取出”我“在群里的昵称子查询
        String nickname_ingroup_SQLFeild = ",(select nickname_ingroup from chat_group_node " +
                "	where node_id = '" + channelId + "' and user_uid = '" + myUserId + "') as nickname_ingroup ";
        // 取出”我“是否在此群里的子查询（存在则返回1，不存在则返回0，返回-1表示不需要查询此值）
        String im_in_group_SQLField = "," + DBDepend.getNVLFunc(
                "(select 1 from chat_group_node where node_id = '" + channelId + "' and user_uid='" + myUserId + "')", "0")
                + " as isInGroup ";

        StringBuilder sb = new StringBuilder();
        sb.append("select b.node_id")           // 群id
                .append("	,b.g_status")        // 群状态
                .append("	,b.node_name")          // 群名称
                .append("	,b.g_owner_user_uid")// 群主uid
                .append("	,b.g_notice")        // 群公告
//			.append("	,b.msg_no_promt")    // 免打扰状态
                .append("	,b.max_member_count")// 允许的最大群员数
                .append("	,b.g_member_count ") // 当前总群员数
                .append("	,c.nickname ")       // 群主昵称
                // "我"在本群的昵称
                .append(needGetMyselfInfo ? nickname_ingroup_SQLFeild : "	,null as  nickname_ingroup ")

                .append("	,b.g_notice_updatetime ")// 群公告更新时间
                .append("	,b.g_notice_updateuid ") // 群公告更新者
                .append("	,d.nickname as nickname_ingroup ")   // 群公告更新者昵称
                .append("	,b.create_time ")        // 群创建时间
                // 取出”我“是否在此群里的子查询（存在则返回1，不存在则返回0，返回-1表示不需要查询此值）
                .append(needGetMyselfInfo ? im_in_group_SQLField : ",-1 as isInGroup ")
                .append("	,e.nickname as create_user_name ")    // 群创建者昵称
                .append("from ")
                .append("(")
                .append("	select * from chat_group_node where node_id = '" + channelId + "'")
                .append(")b ")
                .append("left join g_users c on b.g_owner_user_uid = c.user_uid ")
                .append("left join g_users d on b.g_notice_updateuid = d.user_uid ")
                .append("left join g_users e on b.create_user_uid = e.user_uid ");

        Vector<Vector<?>> vv = db.queryData(sb.toString());
        if (!vv.isEmpty())
            return constructGroupEntityFromQueryRow(vv.get(0));

        return null;
    }

    /**
     * 解析数据库中查询出的群基本信息，并组装成对象，方便使用。
     * <p>
     * 注意：本方法中对数据库原始行数据的解析顺序、字段意义的改动，直接会影响到
     * 方法 {@link #queryGroupInfo(String, String)}、{@link #queryGroupInfoList(String)}
     * 期望的数据结果。所以如果改动本方法，则一定要对应的改动这两个方法！
     *
     * @see #queryGroupInfo(String, String)
     * @see #queryGroupInfoList(String)
     */
    private GroupEntity constructGroupEntityFromQueryRow(Vector<?> row) {
        GroupEntity gee = new GroupEntity();
        gee.setG_id((String) row.get(0));
        gee.setG_status((String) row.get(1));
        gee.setG_name((String) row.get(2));
        gee.setG_owner_user_uid((String) row.get(3));
        gee.setG_notice((String) row.get(4));
//		gee.setMsg_no_promt((String)row.get(5));
        gee.setMax_member_count((String) row.get(5));
        gee.setG_member_count((String) row.get(6));
        gee.setG_owner_name((String) row.get(7));
        gee.setNickname_ingroup((String) row.get(8));

        gee.setG_notice_updatetime((String) row.get(9));
        gee.setG_notice_updateuid((String) row.get(10));
        gee.setG_notice_updatenick((String) row.get(11));

        gee.setCreate_time((String) row.get(12));
        gee.setImIsInGroup((String) row.get(13));
        gee.setCreate_user_name((String) row.get(14));
        return gee;
    }

    private GroupEntity constructChannelEntityFromQueryRow(Vector<?> row) {
        GroupEntity gee = new GroupEntity();
        gee.setG_id((String) row.get(0));
        gee.setG_status((String) row.get(1));
        gee.setG_name((String) row.get(2));
        gee.setG_owner_user_uid((String) row.get(3));
        gee.setG_notice((String) row.get(4));
//		gee.setMsg_no_promt((String)row.get(5));
        gee.setMax_member_count((String) row.get(5));
        gee.setG_member_count((String) row.get(6));
        gee.setG_owner_name((String) row.get(7));

        gee.setG_notice_updatetime((String) row.get(8));
        gee.setG_notice_updateuid((String) row.get(9));
        gee.setG_notice_updatenick((String) row.get(10));

        gee.setCreate_time((String) row.get(11));
        gee.setImIsInGroup((String) row.get(12));
        gee.setCreate_user_name((String) row.get(13));
        gee.setCreateUserId((String) row.get(14));
        return gee;
    }

    /**
     * 加群预编译SQL.
     *
     * @param uidBeInsert 被加入或邀请人UI
     * @param gidBeInsert 被加入的群
     * @param inviteUid   邀请加群的发起人
     */
    private static void prepareInsertMemberToGroup(Vector<Object> sqls, Vector<Object> values
            , String uidBeInsert, String gidBeInsert, String inviteUid, String nodePid, String nodeType, String
                                                           nodeRid) {
        sqls.add("INSERT INTO chat_group_node(user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid" +
                ") VALUES(?,?," + DBDepend.getDefaultDatetimeFunc() + ",?," + DBDepend.getDefaultDatetimeFunc() + ",?,?,?" + ")");
        values.add(new Object[]{uidBeInsert, gidBeInsert, inviteUid, nodePid, nodeType, nodeRid});
    }

    /**
     * 更新群内人数预编译SQL.
     *
     * @param gid 要更新人数的群id
     */
    private static void prepareUpdateGroupMemberCount(Vector<Object> sqls, Vector<Object> values, String gid) {
        sqls.add("update chat_group_base set g_member_count=" +
                "(select count(*) from chat_group_node where base_id=? and node_type='" + NodeType.USER.name() + "') where g_id=?");
        values.add(new Object[]{gid, gid});
    }

    private static void prepareUpdateChannelMemberCount(Vector<Object> sqls, Vector<Object> values, String channelId) throws
            Exception {
        Vector<Vector<?>> vectors = db.queryData("select count(*) from chat_group_node where node_pid = '" + channelId + "' and node_type = '" + NodeType.USER.name() + "'");
        if (!vectors.isEmpty()) {
            sqls.add("update chat_group_node set g_member_count = ? where node_id = ?");
            values.add(new Object[]{vectors.get(0).get(0), channelId});
        }
    }

    /**
     * 从数据库中查询指定用户是否是该群群主。
     *
     * @param gid           被查询的群
     * @param theUidBeQuery 被查询的人
     */
    private static boolean queryGroupOwner(String gid, String theUidBeQuery) throws Exception {
        return !db.queryData("select 1 from chat_group_base where g_owner_user_uid='"
                + theUidBeQuery + "' and g_id='" + gid + "'").isEmpty();
    }

    private static boolean queryChannelOwner(String gid, String theUidBeQuery) throws Exception {
        return !db.queryData("select 1 from chat_group_node where m_ids like '%," + theUidBeQuery + ",%' and base_id ='" + gid + "'").isEmpty();
    }

    /**
     * 创建群组添加群组节点
     *
     * @param gid 群id
     */
    private static void prepareUpdateGroupNote(Vector<Object> sqls, Vector<Object> values, String gid) throws Exception {

        Vector<Vector<?>> members = db.queryData("select node_id from chat_group_node where base_id='"
                + gid + "' and node_type='" + NodeType.MAIN_CHANNEL.name() + "'");
        if (!members.isEmpty()) {
            sqls.add("update chat_group_node set node_pid=?,node_rid=? " +
                    "where base_id=?");
            values.add(new Object[]{members.get(0).get(0), members.get(0).get(0), gid});
        }

    }


    /**
     * 创建子频道
     *
     * @param gid      群ID
     * @param createId 创建者ID
     * @param nodeName 频道名称
     */
    private void createChildChanel(Vector<Object> sqls, Vector<Object> values, String gid, String createId, String nodeName) throws
            Exception {
        Vector<Vector<?>> members = db.queryData("select node_id,node_rid from chat_group_node where base_id='"
                + gid + "' and node_id=node_rid");
        if (!members.isEmpty()) {
            sqls.add("insert into chat_group_node(user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid,node_name" +
                    ") values(?,?," + DBDepend.getDefaultDatetimeFunc() + ",?," + DBDepend.getDefaultDatetimeFunc() + ",?,?,?,?" + ")");
            values.add(new Object[]{0, gid, createId, members.get(0).get(0), NodeType.SUB_CHANNEL.name(), members.get(0).get(1), nodeName});
        }
    }

    /**
     * 修改子频道名称
     *
     * @param node_id  频道ID
     * @param nodeName 频道名称
     */
    private void updateChildChanel(Vector<Object> sqls, Vector<Object> values, String node_id, String nodeName) throws Exception {
        sqls.add("update chat_group_node set node_name=? where node_id=?");
        values.add(new Object[]{nodeName, node_id});

    }

    /**
     * 删除子频道
     */
    private void deleteChildChanel(Vector<Object> sqls, Vector<Object> values, String node_id, String baseId) throws Exception {
        sqls.add("delete from chat_group_node where node_id = ? and base_id = ? and node_type != 'MAIN_CHANNEL'");
        values.add(new Object[]{node_id, baseId});
    }

    /**
     * 更新群组成员节点
     *
     * @param sqls
     * @param values
     * @param node_id
     * @param gid
     */
    private boolean updateChildMemberNode(Vector<Object> sqls, Vector<Object> values, String node_id, String gid, User user) throws Exception {
        db.update(Collections.singletonList("update g_users set curr_node_id = '" + node_id + "' where user_uid = '" + user.getUserId() + "'"), true);
        Vector<Vector<?>> vectors = db.queryData("select count(1) from chat_group_node where g_status = 1 and node_type = 'USER' and base_id = '" + gid + "' and node_pid = '" + node_id + "' and user_uid = '" + user.getUserId() + "'");
        if (vectors.get(0).get(0).toString().equals("0")) {
            // 指挥员退出历史切换频道
            Vector<Vector<?>> exist = db.queryData("select count(1) from chat_group_node where g_status = 1 and node_type = 'USER' and base_id = '" + gid + "' and owner is false and user_uid = '" + user.getUserId() + "'");
            if (!exist.get(0).get(0).toString().equals("0")) {
                db.update(Collections.singletonList("update chat_group_node set g_status = -1 where node_type = 'USER' and owner is false and base_id = '" + gid + "' and user_uid = '" + user.getUserId() + "'"), true);
            }

            // 指挥员切换新频道(添加指挥员入频道)
            Vector<Vector<?>> parentChannel = db.queryData("select m_ids,level,s_ids from chat_group_node where node_id = '" + node_id + "'");
            if (!parentChannel.isEmpty()) {
                String userId = IdUtils.getNumberUuid();
                String time = DateUtil.format(new Date(), NORM_DATETIME_PATTERN);
                String mIds = parentChannel.get(0).get(0).toString();
                int level = Integer.parseInt(parentChannel.get(0).get(1).toString());
                String sIds = parentChannel.get(0).get(2).toString();
                sqls.add("INSERT INTO chat_group_node(node_id,user_uid,base_id,join_time,be_invite_user_id,msg_time_start,node_pid,node_type,node_rid,node_name,create_time,create_user_uid,m_ids,level,s_ids,owner" +
                        ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
                values.add(new Object[]{userId, user.getUserId(), gid, time, user.getUserId(), time, node_id, NodeType.USER.name(), gid, user.getNickname(), time, user.getUserId(), mIds, level + 1, sIds, false});
                //统计
                prepareUpdateChannelMemberCount(sqls, values, node_id);
                boolean update = LogicProcessor2.db.update(sqls, values, true);

                // 通知
                GroupEntity newGroupInfoReturn = this.queryChannelInfo(node_id, user.getUserId());// 第2个参数null表示不需要取”我“在本群中的昵称，因为刚建的群还来不及设置群昵称呢
                ArrayList<GroupMemberEntity> newJoinedMemberList = new ArrayList<>();
                ConcurrentHashMap<String, GroupMember4Cache> hashMap = GroupsMembersCacheProvider.getInstance().get(gid + "_" + node_id);
                GroupMemberEntity groupMemberEntity = new GroupMemberEntity();
                groupMemberEntity.setUser_uid(user.getUserId());
                groupMemberEntity.setNickname(user.getNickname());
                groupMemberEntity.setG_id(gid);
                newJoinedMemberList.add(groupMemberEntity);
                inviteNotify(gid, user.getUserId(), user.getNickname(), "0", newJoinedMemberList, hashMap != null ? hashMap.values() : null, newGroupInfoReturn, node_id);
                GroupsInfoCacheProvider.getInstance().reloadOneFromDB(gid + "_" + node_id);
                return update;
            }
        }
        return false;
    }

    /**
     * 获取频道列表
     */
    private List<ChannelEntity> queryChannel(String gid, User user) throws Exception {
        List<ChannelEntity> list = new ArrayList<>();
        Vector<Vector<?>> v = db.queryData("select count(1) from chat_group_node where g_status = 1 and node_type = 'MAIN_CHANNEL' and base_id = '" + gid + "' and s_ids like '%," + user.getUserId() + ",%'");
        boolean isZhihui = !v.isEmpty() && !v.get(0).get(0).toString().equals("0");
        if (!isZhihui) {
            String sql = "select node_pid from chat_group_node where base_id = '" + gid + "' and user_uid = '" + user.getUserId() + "' and node_type = 'USER' and g_status = 1";
            Vector<Vector<?>> channel = db.queryData(sql);
            if (!channel.isEmpty()) {
                String ids = channel.stream().map(a -> a.get(0).toString()).collect(Collectors.joining("','"));
                Vector<Vector<?>> res = db.queryData("select node_id,node_type,node_name from chat_group_node where  node_id in( '" + ids + "')");
                for (Vector<?> vector : res) {
                    ChannelEntity entity = new ChannelEntity();
                    entity.setNodeId(vector.get(0).toString());
                    entity.setNodeType(vector.get(1).toString());
                    entity.setNodeName(vector.get(2).toString());
                    entity.setmUsers(iterateManagersByCurrentUser(user.getUserId(), gid, entity.getNodeId()));
                    list.add(entity);
                }
            }
        } else {
            String sql = "select node_pid from chat_group_node where base_id = '" + gid + "' and owner is true and user_uid = '" + user.getUserId() + "' and node_type = 'USER' and g_status = 1";
            Vector<Vector<?>> parent = db.queryData(sql);
            if (!parent.isEmpty()) {
                parent.forEach(p -> {
                    try {
                        String channelId = p.get(0).toString();
                        Vector<Vector<?>> pChannel = db.queryData("select node_id,node_type,node_name from chat_group_node where g_status = 1 and node_type = 'MAIN_CHANNEL' and base_id = '" + gid + "' and node_id = '" + channelId + "'");
                        ChannelEntity entity = new ChannelEntity();
                        entity.setNodeId(pChannel.get(0).get(0).toString());
                        entity.setNodeType(pChannel.get(0).get(1).toString());
                        entity.setNodeName(pChannel.get(0).get(2).toString());
                        entity.setOwner(true);
                        entity.setOnekey(false);
                        entity.setmUsers(iterateManagersByCurrentUser(user.getUserId(), gid, entity.getNodeId()));
                        list.add(entity);
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                });
            }
            Vector<Vector<?>> channels = db.queryData("select node_id,node_type,node_name from chat_group_node where g_status = 1 and node_type = 'MAIN_CHANNEL' and base_id = '" + gid + "' and s_ids like '%," + user.getUserId() + ",%'");
            if (!channels.isEmpty()) {
                List<String> os = new ArrayList<>();
                List<String> collect = list.stream().map(ChannelEntity::getNodeId).collect(Collectors.toList());
                for (Vector<?> vec : channels) {
                    String nodeId = vec.get(0).toString();
                    if (!collect.contains(nodeId)) {
                        ChannelEntity entity = new ChannelEntity();
                        entity.setNodeId(vec.get(0).toString());
                        entity.setNodeType(vec.get(1).toString());
                        entity.setNodeName(vec.get(2).toString());
                        entity.setOwner(false);
                        entity.setOnekey(true);
                        entity.setmUsers(iterateManagersByCurrentUser(user.getUserId(), gid, entity.getNodeId()));
                        list.add(entity);
                    } else {
                        os.add(nodeId);
                    }
                }
                list.forEach(a -> {
                    if (os.contains(a.getNodeId())) {
                        a.setOnekey(true);
                    }
                });
            }
            return list.stream().sorted(Comparator.comparing(ChannelEntity::getOwner).reversed()).collect(Collectors.toList());
        }
        return list;
    }

    private List<GroupMemberEntity> queryChannelMemberList2(String nodeId, User user) throws Exception {
        StringBuilder sb = new StringBuilder()
                .append("select ")
                .append("	a.user_uid ")
                .append("	,a.base_id ")
                .append("	,a.node_id ").append("	,a.node_pid ").append("  ,a.node_type")
                .append("	," + DBDepend.getNVLFunc("a.nickname_ingroup", "b.nickname") + " as nname ")
                .append("	,b.user_avatar_file_name ")
                .append(", b.user_type ")
                .append(", b.is_online ")
                .append(" FROM ")
                .append("(")
                // 使用子查询提升查询性能
                .append("	select user_uid,base_id,nickname_ingroup,node_id,node_pid,node_type from chat_group_node where g_status = 1 and node_pid ='" + nodeId + "' ")
                .append(" and node_type='" + NodeType.USER.name() + "'")
                .append(") a ")
                .append("left join g_users b on a.user_uid = b.user_uid ")
                // 本条件将限制只能查到正常状态下的群成员列表（使用EXISTS语句作为条件是为了提升查询性能）
                .append("where b.del_flag = 0 and  EXISTS (select 1 from chat_group_base c where a.base_id = c.g_id and c.g_status=1) ");

        // 群员列表数据库行数据
        UsersStatusManager liverUsersMgr = ChatServerEventListener.getInstance().getLiverUsersMgr();
        Vector<Vector<?>> members = db.queryData(sb.toString());
        ArrayList<GroupMemberEntity> membersToClient = new ArrayList<GroupMemberEntity>();
        // 遍历行数据，组装成对象List
        for (Vector<?> row : members) {
            GroupMemberEntity gme = new GroupMemberEntity();
            int i = 0;
            String user_uid = (String) row.get(i++);
            gme.setUser_uid(user_uid);
            gme.setG_id((String) row.get(i++));
            gme.setNode_id(row.get(i++).toString());
            gme.setNode_pid(row.get(i++).toString());
            Set<String> keySet = RedisUtil.keys(RtcRedisKeyConstants.DEVICE_LIVE_KEYS(gme.getG_id()));
            List<String> g = keySet.stream().filter(a -> a.contains(gme.getG_id()) && a.contains(user_uid)).collect(Collectors.toList());
            int ispush = 0;
            for (String k : g) {
                if (RedisUtil.get(k) != null) {
                    ispush = 1;
                    break;
                }
            }
            gme.setIsPush(ispush);
            gme.setNode_type((String) row.get(i++));
            gme.setNickname((String) row.get(i++));
            gme.setUserAvatarFileName((String) row.get(i++));
            gme.setUserType(Integer.parseInt(row.get(i++).toString()));
            if (gme.getUserType() == 2) {
                gme.setIsOnline(Integer.parseInt(row.get(i).toString()));
            } else {
                if (liverUsersMgr.getLiveUsers().containsKey(user_uid)) {
                    gme.setIsOnline(1);
                } else {
                    gme.setIsOnline(Integer.parseInt(row.get(i).toString()));
                }
            }
            membersToClient.add(gme);
        }

//        if (user.getAndroid()) {
        Vector<Vector<?>> group = db.queryData("select base_id from chat_group_node where g_status = 1 and node_type = 'MAIN_CHANNEL' and node_id = '" + nodeId + "'");
        List<String> userInfoDTOS = iterateManagersByCurrentUser(user.getUserId(), group.get(0).get(0).toString(), nodeId).stream().map(UserInfoDTO::getUserUid).collect(Collectors.toList());
//            List<String> mIds = userInfoDTOS.stream().map(UserInfoDTO::getUserUid).collect(Collectors.toList());
//            List<GroupMemberEntity> res = membersToClient.stream().filter(e -> !mIds.contains(e.getUser_uid())).collect(Collectors.toList());
//            return res.stream().sorted(Comparator.comparing(GroupMemberEntity::getIsOnline, Comparator.reverseOrder())).collect(Collectors.toList());
//        } else {


        List<GroupMemberEntity> managers = membersToClient.stream().filter(a -> userInfoDTOS.contains(a.getUser_uid())).collect(Collectors.toList());
        List<GroupMemberEntity> sortManagers = managers.stream().sorted(Comparator.comparing(GroupMemberEntity::getIsOnline, Comparator.reverseOrder())).collect(Collectors.toList());
        List<GroupMemberEntity> noManagers = membersToClient.stream().filter(a -> !userInfoDTOS.contains(a.getUser_uid())).collect(Collectors.toList());
        List<GroupMemberEntity> sortNoManagers = noManagers.stream().sorted(Comparator.comparing(GroupMemberEntity::getIsOnline, Comparator.reverseOrder())).collect(Collectors.toList());
        sortManagers.addAll(sortNoManagers);
        return sortManagers;

    }

    /**
     * 查询指定群组的某个频道成员列表。
     * <p>
     * <b>注意：</b>如果用于大量频繁读取且只需要群成员id的场景下，请使用
     * {@link GroupsMembersCacheProvider#get(String)}缓存，从而提升性能，
     * 防止频繁读取DB这种慢IO拖慢系统性能且有可能导致DB瓶颈。
     *
     * @param nodeId
     * @see GroupsMembersCacheProvider#get(String)
     */
    private List<GroupMemberEntity> queryChannelMemberList(String nodeId, User user) throws Exception {
        StringBuilder sb = new StringBuilder()
                .append("select ")
                .append("	a.user_uid ")
                .append("	,a.base_id ")
                .append("	,a.node_id ").append("	,a.node_pid ").append("  ,a.node_type")
                .append("	," + DBDepend.getNVLFunc("a.nickname_ingroup", "b.nickname") + " as nname ")
                .append("	,b.user_avatar_file_name ")
                .append(" FROM ")
                .append("(")
                // 使用子查询提升查询性能
                .append("	select user_uid,base_id,nickname_ingroup,node_id,node_pid,node_type from chat_group_node where g_status = 1 and node_pid ='" + nodeId + "' ")
                .append(" and node_type='" + NodeType.USER.name() + "'")
                .append(") a ")
                .append("left join g_users b on a.user_uid = b.user_uid ")
                // 本条件将限制只能查到正常状态下的群成员列表（使用EXISTS语句作为条件是为了提升查询性能）
                .append("where b.del_flag = 0 and  EXISTS (select 1 from chat_group_base c where a.base_id = c.g_id and c.g_status=1) ");

        // 群员列表数据库行数据
        UsersStatusManager liverUsersMgr = ChatServerEventListener.getInstance().getLiverUsersMgr();
        Vector<Vector<?>> members = db.queryData(sb.toString());
        ArrayList<GroupMemberEntity> membersToClient = new ArrayList<GroupMemberEntity>();
        Map<String, String> videoMap = UserProtocalsType.GROUP_VIDEO_MAP;
        // 遍历行数据，组装成对象List
        for (Vector<?> row : members) {
            GroupMemberEntity gme = new GroupMemberEntity();
            int i = 0;
            gme.setIsOnline(liverUsersMgr.isOnline((String) row.get(i)) ? 1 : 0);
            String user_uid = (String) row.get(i++);
            gme.setUser_uid(user_uid);
            gme.setG_id((String) row.get(i++));
            gme.setNode_id(row.get(i++).toString());
            gme.setNode_pid(row.get(i++).toString());
            Set<String> keys = videoMap.keySet();
            List<String> g = keys.stream().filter(a -> a.contains(gme.getG_id() + "_") && a.contains("-" + user_uid)).collect(Collectors.toList());
            int ispush = 0;
            for (String k : g) {
                if (videoMap.get(k) != null) {
                    ispush = 1;
                    break;
                }
            }
            gme.setIsPush(ispush);
            gme.setNode_type((String) row.get(i++));
            gme.setNickname((String) row.get(i++));
            gme.setUserAvatarFileName((String) row.get(i++));
            membersToClient.add(gme);
        }

        Vector<Vector<?>> group = db.queryData("select base_id from chat_group_node where g_status = 1 and node_type = 'MAIN_CHANNEL' and node_id = '" + nodeId + "'");
        List<String> userInfoDTOS = iterateManagersByCurrentUser(user.getUserId(), group.get(0).get(0).toString(), nodeId).stream().map(UserInfoDTO::getUserUid).collect(Collectors.toList());
        List<GroupMemberEntity> managers = membersToClient.stream().filter(a -> userInfoDTOS.contains(a.getUser_uid())).collect(Collectors.toList());
        List<GroupMemberEntity> sortManagers = managers.stream().sorted(Comparator.comparing(GroupMemberEntity::getIsOnline, Comparator.reverseOrder())).collect(Collectors.toList());
        List<GroupMemberEntity> noManagers = membersToClient.stream().filter(a -> !userInfoDTOS.contains(a.getUser_uid())).collect(Collectors.toList());
        List<GroupMemberEntity> sortNoManagers = noManagers.stream().sorted(Comparator.comparing(GroupMemberEntity::getIsOnline, Comparator.reverseOrder())).collect(Collectors.toList());
        sortManagers.addAll(sortNoManagers);
        return sortManagers;

    }

    /**
     * 获取用户频道号
     */
    private String queryChannelForUser(String gid, String user_uid) throws Exception {
        Vector<Vector<?>> vectors = db.queryData("select curr_node_id from g_users where user_uid = '" + user_uid + "' and del_flag = 0 ");
        if (!vectors.isEmpty() && vectors.get(0).get(0) != null) {
            Vector<Vector<?>> channel = db.queryData("select node_id,node_name from chat_group_node where base_id = '" + gid + "' and node_id = '" + vectors.get(0).get(0) + "' and g_status = 1 and node_type = 'MAIN_CHANNEL'");
            if (!channel.isEmpty()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("channelId", channel.get(0).get(0));
                jsonObject.put("channelName", channel.get(0).get(1));
                return jsonObject.toString();
            }
        } else {
            Vector<Vector<?>> channel = db.queryData("select node_id,node_name from chat_group_node where base_id = '" + gid + "' and node_id = '" + gid + "' and g_status = 1 and node_type = 'MAIN_CHANNEL'");
            if (!channel.isEmpty()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("channelId", channel.get(0).get(0));
                jsonObject.put("channelName", channel.get(0).get(1));
                return jsonObject.toString();
            }
        }
        return null;
    }

    /**
     * 获取云盘文件列表
     *
     * @param groupId    群id
     * @param type       分类： 1 视频  2 图片
     * @param startTime  筛选开始时间
     * @param endtime    筛选结束时间
     * @param pageNumber 当前页
     * @param pageSize   分页条数
     */
    private String queryCloudFileByGroup(String groupId, Integer type, String startTime, String endtime, Integer
            pageNumber, Integer pageSize, String userUid, Integer storeType) throws Exception {
        long total = 0L;
        groupId = groupId.contains("_") ? groupId.split("_")[0] : groupId;
        StringBuilder builder = new StringBuilder();
        builder.append("select count(*) from t_cloud where g_id like '").append(groupId).append("%'");
        if (!Objects.isNull(type) && type != 0) {
            builder.append(" and file_type=").append(type);
        }
        if (EmptyUtils.isNotEmpty(startTime)) {
            builder.append(" and create_time>='").append(startTime).append("' ");
        }
        if (EmptyUtils.isNotEmpty(endtime)) {
            builder.append(" and create_time<='").append(endtime).append("' ");
        }
        if (EmptyUtils.isNotEmpty(userUid)) {
            builder.append(" and create_uid = '").append(userUid).append("' ");
        }
        if (storeType != null && storeType == 2) {
            builder.append(" and store_type = 2 ");
        } else {
            builder.append(" and store_type != 2 ");
        }
        Vector<Vector<?>> count = db.queryData(builder.toString());
        if (!count.isEmpty()) {
            total = Long.parseLong((String) count.get(0).get(0));
        }
        StringBuilder sb = new StringBuilder();
        sb.append("select ")
                .append("a.* ")
                .append(",b.nickname ")
                .append(" FROM ")
                .append(" t_cloud a ")
                .append("left join g_users b on a.create_uid = b.user_uid ")
                .append("where ").append("a.g_id like '").append(groupId).append("%' ");
        //type没有传或者传0 查询全部
        if (!Objects.isNull(type) && type > 0) {
            sb.append("and a.file_type=").append(type).append(" ");
        }
        if (EmptyUtils.isNotEmpty(startTime)) {
            sb.append("and a.create_time>='").append(startTime).append("' ");
        }
        if (EmptyUtils.isNotEmpty(endtime)) {
            sb.append("and a.create_time<='").append(endtime).append("' ");
        }
        if (EmptyUtils.isNotEmpty(userUid)) {
            sb.append(" and a.create_uid = '").append(userUid).append("' ");
        }
        if (null != storeType && 2 == storeType) {
            sb.append(" and a.store_type = 2 ");
        } else {
            sb.append(" and a.store_type != 2 ");
        }
        sb.append(" order by a.create_time desc ");
        if (!Objects.isNull(pageNumber) && pageNumber > 0) {
            //默认分页15条
            pageSize = Objects.isNull(pageSize) ? 15 : pageSize;
            Integer pageNum = countPageNumber(pageNumber, pageSize);
            sb.append("limit " + pageNum + "," + pageSize);
        }

        Vector<Vector<?>> list = LogicProcessor2.db.queryData(sb.toString());
        List<CloudFileVo> vos = new ArrayList<>();
        for (Vector<?> v : list) {
            CloudFileVo vo = new CloudFileVo();
            int i = 0;
            vo.setId(Integer.valueOf(v.get(i++).toString()));
            vo.setgId(v.get(i++).toString());
            vo.setCreateUId(v.get(i++).toString());
            vo.setCreateTime(v.get(i++).toString());
            vo.setUpdateTime(v.get(i++).toString());
            vo.setFileName(v.get(i++).toString());
            vo.setFileType(Integer.valueOf(v.get(i++).toString()));
            vo.setFilesize(Long.valueOf(v.get(i++).toString()));
            vo.setFileMd5(v.get(i++).toString());
            vo.setStoreType(v.get(i++).toString());
            vo.setNickName(v.get(i++).toString());
            vos.add(vo);
        }
        PageData pageData = new PageData();
        pageData.setRecords(vos);
        pageData.setTotal(total);
        pageData.setPageNumber(pageNumber);
        pageData.setPageSize(list.size());
        return new Gson().toJson(pageData);
    }


    private Integer countPageNumber(Integer pageNumber, Integer pagrSize) {
        return (pageNumber - 1) * pagrSize;
    }

}
